Device Auth. Grant - redden device token, get token

This commit is contained in:
Dusan Jakub
2023-09-18 14:17:37 +02:00
parent e464146476
commit 2b2616cbe7
4 changed files with 45 additions and 14 deletions

View File

@@ -3,7 +3,6 @@ package com.ysoft.geecon;
import com.ysoft.geecon.dto.*;
import com.ysoft.geecon.error.OAuthException;
import com.ysoft.geecon.repo.ClientsRepo;
import com.ysoft.geecon.repo.SecureRandomStrings;
import com.ysoft.geecon.repo.SessionsRepo;
import com.ysoft.geecon.repo.UsersRepo;
import io.quarkus.qute.CheckedTemplate;
@@ -116,6 +115,7 @@ public class OAuthResource {
public AccessTokenResponse token(TokenParams params) {
return switch (params.getGrantType()) {
case "authorization_code" -> redeemAuthorizationCode(params);
case "urn:ietf:params:oauth:grant-type:device_code" -> redeemDeviceCode(params);
default -> throw new OAuthException("Unsupported grant type");
};
}
@@ -143,22 +143,25 @@ public class OAuthResource {
}
private AccessTokenResponse redeemAuthorizationCode(TokenParams params) {
validateClient(params);
var session = sessionsRepo.redeemAuthorizationCode(params.getCode())
.orElseThrow(() -> new OAuthException("Invalid code"));
validateClient(params, session);
if (!session.validateCodeChallenge(params.getCodeVerifier())) {
throw new OAuthException("Invalid code verifier");
}
return session.tokens();
}
String idToken = null;
return new AccessTokenResponse("Bearer",
8400,
SecureRandomStrings.alphanumeric(50),
session.scope(),
SecureRandomStrings.alphanumeric(50),
idToken
);
private AccessTokenResponse redeemDeviceCode(TokenParams params) {
var session = sessionsRepo.getByAuthorizationCode(params.getDeviceCode())
.orElseThrow(() -> new OAuthException("Invalid code"));
validateClient(params, session);
if (session.tokens() != null) {
sessionsRepo.redeemAuthorizationCode(params.getDeviceCode());
return session.tokens();
} else {
throw new OAuthException("Authorization pending");
}
}
private User validateUser(String username, String password) {
@@ -179,10 +182,10 @@ public class OAuthResource {
return client;
}
private OAuthClient validateClient(TokenParams params) {
private OAuthClient validateClient(TokenParams params, AuthorizationSession session) {
var client = clientsRepo.getClient(params.getClientId())
.orElseThrow(() -> new RuntimeException("Not a valid client"));
if (!client.validateRedirectUri(params.getRedirectUri())) {
if (!session.validateRedirectUri(params.getRedirectUri())) {
throw new RuntimeException("Invalid redirect URI");
}
if (!client.validateSecret(params.getClientSecret())) {

View File

@@ -3,6 +3,7 @@ package com.ysoft.geecon.dto;
import com.ysoft.geecon.repo.SecureRandomStrings;
import java.util.List;
import java.util.Objects;
public record AuthorizationSession(String sessionId,
AuthParams params,
@@ -48,4 +49,7 @@ public record AuthorizationSession(String sessionId,
return Pkce.validate(params.codeChallengeMethod, params.codeChallenge, codeVerifier);
}
public boolean validateRedirectUri(String redirectUri) {
return Objects.equals(params.redirectUri, redirectUri);
}
}

View File

@@ -22,6 +22,9 @@ public class TokenParams {
@FormParam("code_verifier")
private String codeVerifier;
@FormParam("device_code")
private String deviceCode;
public String getGrantType() {
return grantType;
}
@@ -69,4 +72,12 @@ public class TokenParams {
public void setCodeVerifier(String codeVerifier) {
this.codeVerifier = codeVerifier;
}
public String getDeviceCode() {
return deviceCode;
}
public void setDeviceCode(String deviceCode) {
this.deviceCode = deviceCode;
}
}

View File

@@ -68,6 +68,19 @@ public class DeviceAuthGrantTest {
when().
post("auth/consent")
.then().statusCode(200);
}
given().
formParam("grant_type", "urn:ietf:params:oauth:grant-type:device_code").
formParam("client_id", "myclient").
formParam("device_code", deviceResponse.deviceCode()).
when().
post("/auth/token")
.then()
.statusCode(200)
.contentType(JSON)
.body("token_type", is(notNullValue()))
.body("expires_in", is(notNullValue()))
.body("access_token", is(notNullValue()))
.body("refresh_token", is(notNullValue()));
}
}