mirror of
https://github.com/ysoftdevs/oauth-playground-server.git
synced 2026-03-27 19:42:02 +01:00
Token Endpoint
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -40,6 +40,10 @@
|
|||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-resteasy-reactive-qute</artifactId>
|
<artifactId>quarkus-resteasy-reactive-qute</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-junit5</artifactId>
|
<artifactId>quarkus-junit5</artifactId>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package com.ysoft.geecon;
|
package com.ysoft.geecon;
|
||||||
|
|
||||||
import com.ysoft.geecon.dto.AuthParams;
|
import com.ysoft.geecon.dto.*;
|
||||||
import com.ysoft.geecon.dto.OAuthClient;
|
|
||||||
import com.ysoft.geecon.dto.User;
|
|
||||||
import com.ysoft.geecon.error.OAuthException;
|
import com.ysoft.geecon.error.OAuthException;
|
||||||
import com.ysoft.geecon.repo.ClientsRepo;
|
import com.ysoft.geecon.repo.ClientsRepo;
|
||||||
|
import com.ysoft.geecon.repo.SecureRandomStrings;
|
||||||
import com.ysoft.geecon.repo.SessionsRepo;
|
import com.ysoft.geecon.repo.SessionsRepo;
|
||||||
import com.ysoft.geecon.repo.UsersRepo;
|
import com.ysoft.geecon.repo.UsersRepo;
|
||||||
import io.quarkus.qute.CheckedTemplate;
|
import io.quarkus.qute.CheckedTemplate;
|
||||||
@@ -17,6 +16,7 @@ import jakarta.ws.rs.core.Response;
|
|||||||
import jakarta.ws.rs.core.UriBuilder;
|
import jakarta.ws.rs.core.UriBuilder;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Path("/auth")
|
@Path("/auth")
|
||||||
public class OAuthResource {
|
public class OAuthResource {
|
||||||
@@ -40,7 +40,7 @@ public class OAuthResource {
|
|||||||
public TemplateInstance get(AuthParams params) {
|
public TemplateInstance get(AuthParams params) {
|
||||||
var client = validateClient(params);
|
var client = validateClient(params);
|
||||||
String sessionId = sessionsRepo.newAuthorizationSession(params, client);
|
String sessionId = sessionsRepo.newAuthorizationSession(params, client);
|
||||||
return Templates.login(params.getLoginHint(), sessionId, "");
|
return Templates.login(params.getLoginHint(), sessionId, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@@ -75,7 +75,34 @@ public class OAuthResource {
|
|||||||
.queryParam("state", params.getState())
|
.queryParam("state", params.getState())
|
||||||
.build())
|
.build())
|
||||||
.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) {
|
private User validateUser(String username, String password) {
|
||||||
return usersRepo.getUser(username)
|
return usersRepo.getUser(username)
|
||||||
@@ -95,6 +122,17 @@ public class OAuthResource {
|
|||||||
return client;
|
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;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
public class AuthParams {
|
public class AuthParams {
|
||||||
public enum ResponseType {
|
|
||||||
code
|
|
||||||
}
|
|
||||||
|
|
||||||
@RestQuery("login_hint")
|
@RestQuery("login_hint")
|
||||||
String loginHint;
|
String loginHint;
|
||||||
@RestQuery("response_type")
|
@RestQuery("response_type")
|
||||||
ResponseType responseType;
|
String responseType;
|
||||||
@RestQuery("client_id")
|
@RestQuery("client_id")
|
||||||
String clientId;
|
String clientId;
|
||||||
@RestQuery("redirect_uri")
|
@RestQuery("redirect_uri")
|
||||||
@@ -31,11 +27,11 @@ public class AuthParams {
|
|||||||
this.loginHint = loginHint;
|
this.loginHint = loginHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseType getResponseType() {
|
public String getResponseType() {
|
||||||
return responseType;
|
return responseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResponseType(ResponseType responseType) {
|
public void setResponseType(String responseType) {
|
||||||
this.responseType = responseType;
|
this.responseType = responseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,4 +14,8 @@ public record AuthorizationSession(AuthParams params, OAuthClient client, User u
|
|||||||
public AuthorizationSession withScopes(List<String> acceptedScopes) {
|
public AuthorizationSession withScopes(List<String> acceptedScopes) {
|
||||||
return new AuthorizationSession(params, client, user, 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;
|
package com.ysoft.geecon.dto;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public record OAuthClient(String clientId, String description, String clientSecret, String redirectUri) {
|
public record OAuthClient(String clientId, String description, String clientSecret, String redirectUri) {
|
||||||
public boolean validateRedirectUri(String redirectUri) {
|
public boolean validateRedirectUri(String redirectUri) {
|
||||||
return this.redirectUri != null && this.redirectUri.equals(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() {
|
public ClientsRepo() {
|
||||||
register(new OAuthClient("my-public-client", "Example public client", null, "https://localhost:8888/oauth_success"));
|
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) {
|
public Optional<OAuthClient> getClient(String clientId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user