mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-01-17 09:07:12 +01:00
Device Auth. Grant - redden device token, get token
This commit is contained in:
@@ -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())) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user