mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-01-16 08:37:11 +01:00
Token Endpoint
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -40,6 +40,10 @@
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-resteasy-reactive-qute</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.ysoft.geecon;
|
||||
|
||||
import com.ysoft.geecon.dto.AuthParams;
|
||||
import com.ysoft.geecon.dto.OAuthClient;
|
||||
import com.ysoft.geecon.dto.User;
|
||||
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;
|
||||
@@ -17,6 +16,7 @@ import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.UriBuilder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Path("/auth")
|
||||
public class OAuthResource {
|
||||
@@ -40,7 +40,7 @@ public class OAuthResource {
|
||||
public TemplateInstance get(AuthParams params) {
|
||||
var client = validateClient(params);
|
||||
String sessionId = sessionsRepo.newAuthorizationSession(params, client);
|
||||
return Templates.login(params.getLoginHint(), sessionId, "");
|
||||
return Templates.login(params.getLoginHint(), sessionId, "");
|
||||
}
|
||||
|
||||
@POST
|
||||
@@ -75,7 +75,34 @@ public class OAuthResource {
|
||||
.queryParam("state", params.getState())
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/token")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public AccessTokenResponse token(TokenParams params) {
|
||||
return switch (params.getGrantType()) {
|
||||
case "authorization_code" -> redeemAuthorizationCode(params);
|
||||
default -> throw new OAuthException("Unsupported grant type");
|
||||
};
|
||||
}
|
||||
|
||||
private AccessTokenResponse redeemAuthorizationCode(TokenParams params) {
|
||||
validateClient(params);
|
||||
var session = sessionsRepo.redeemAuthorizationCode(params.getCode())
|
||||
.orElseThrow(() -> new OAuthException("Invalid code"));
|
||||
|
||||
String idToken = null;
|
||||
|
||||
return new AccessTokenResponse("Bearer",
|
||||
8400,
|
||||
SecureRandomStrings.alphanumeric(50),
|
||||
session.scope(),
|
||||
SecureRandomStrings.alphanumeric(50),
|
||||
idToken
|
||||
);
|
||||
}
|
||||
|
||||
private User validateUser(String username, String password) {
|
||||
return usersRepo.getUser(username)
|
||||
@@ -95,6 +122,17 @@ public class OAuthResource {
|
||||
return client;
|
||||
}
|
||||
|
||||
private OAuthClient validateClient(TokenParams params) {
|
||||
var client = clientsRepo.getClient(params.getClientId())
|
||||
.orElseThrow(() -> new RuntimeException("Not a valid client"));
|
||||
if (!client.validateRedirectUri(params.getRedirectUri())) {
|
||||
throw new RuntimeException("Invalid redirect URI");
|
||||
}
|
||||
if (!client.validateSecret(params.getClientSecret())) {
|
||||
throw new RuntimeException("Invalid secret");
|
||||
}
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.ysoft.geecon.dto;
|
||||
|
||||
public record AccessTokenResponse(String token, String scope, String idToken, long expiresIn) {
|
||||
}
|
||||
public record AccessTokenResponse(String tokenType, long expiresIn, String accessToken, String scope, String refreshToken, String idToken) {
|
||||
}
|
||||
@@ -6,14 +6,10 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class AuthParams {
|
||||
public enum ResponseType {
|
||||
code
|
||||
}
|
||||
|
||||
@RestQuery("login_hint")
|
||||
String loginHint;
|
||||
@RestQuery("response_type")
|
||||
ResponseType responseType;
|
||||
String responseType;
|
||||
@RestQuery("client_id")
|
||||
String clientId;
|
||||
@RestQuery("redirect_uri")
|
||||
@@ -31,11 +27,11 @@ public class AuthParams {
|
||||
this.loginHint = loginHint;
|
||||
}
|
||||
|
||||
public ResponseType getResponseType() {
|
||||
public String getResponseType() {
|
||||
return responseType;
|
||||
}
|
||||
|
||||
public void setResponseType(ResponseType responseType) {
|
||||
public void setResponseType(String responseType) {
|
||||
this.responseType = responseType;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,4 +14,8 @@ public record AuthorizationSession(AuthParams params, OAuthClient client, User u
|
||||
public AuthorizationSession withScopes(List<String> acceptedScopes) {
|
||||
return new AuthorizationSession(params, client, user, acceptedScopes);
|
||||
}
|
||||
|
||||
public String scope() {
|
||||
return acceptedScopes == null ? null : String.join(" ", acceptedScopes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
package com.ysoft.geecon.dto;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record OAuthClient(String clientId, String description, String clientSecret, String redirectUri) {
|
||||
public boolean validateRedirectUri(String redirectUri) {
|
||||
return this.redirectUri != null && this.redirectUri.equals(redirectUri);
|
||||
}
|
||||
|
||||
public boolean validateSecret(String clientSecret) {
|
||||
return Objects.equals(clientSecret, this.clientSecret);
|
||||
}
|
||||
}
|
||||
|
||||
65
src/main/java/com/ysoft/geecon/dto/TokenParams.java
Normal file
65
src/main/java/com/ysoft/geecon/dto/TokenParams.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package com.ysoft.geecon.dto;
|
||||
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import org.jboss.resteasy.reactive.RestQuery;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class TokenParams {
|
||||
|
||||
@FormParam("grant_type")
|
||||
private String grantType;
|
||||
|
||||
@FormParam("client_id")
|
||||
private String clientId;
|
||||
|
||||
@FormParam("client_secret")
|
||||
private String clientSecret;
|
||||
|
||||
@FormParam("redirect_uri")
|
||||
private String redirectUri;
|
||||
|
||||
@FormParam("code")
|
||||
private String code;
|
||||
|
||||
public String getGrantType() {
|
||||
return grantType;
|
||||
}
|
||||
|
||||
public void setGrantType(String grantType) {
|
||||
this.grantType = grantType;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getClientSecret() {
|
||||
return clientSecret;
|
||||
}
|
||||
|
||||
public void setClientSecret(String clientSecret) {
|
||||
this.clientSecret = clientSecret;
|
||||
}
|
||||
|
||||
public String getRedirectUri() {
|
||||
return redirectUri;
|
||||
}
|
||||
|
||||
public void setRedirectUri(String redirectUri) {
|
||||
this.redirectUri = redirectUri;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ public class ClientsRepo {
|
||||
|
||||
public ClientsRepo() {
|
||||
register(new OAuthClient("my-public-client", "Example public client", null, "https://localhost:8888/oauth_success"));
|
||||
register(new OAuthClient("oauthdebugger", "Example public client", null, "https://oauthdebugger.com/debug"));
|
||||
}
|
||||
|
||||
public Optional<OAuthClient> getClient(String clientId) {
|
||||
|
||||
Reference in New Issue
Block a user