Implicit flow

This commit is contained in:
Dusan Jakub
2023-09-15 15:06:58 +02:00
parent 5eecf5ec6d
commit bcba2d00b3
4 changed files with 61 additions and 19 deletions

View File

@@ -16,7 +16,6 @@ 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 {
@@ -69,12 +68,24 @@ public class OAuthResource {
} }
} }
String authCode = sessionsRepo.finishSession(sessionId, scopes); session = sessionsRepo.authorizeSession(sessionId, scopes);
return Response.seeOther(UriBuilder.fromUri(params.getRedirectUri())
.queryParam("code", authCode) var responseTypes = params.getResponseTypes();
.queryParam("state", params.getState())
.build()) UriBuilder uri = UriBuilder.fromUri(params.getRedirectUri())
.build(); .fragment("")
.queryParam("state", params.getState());
if (responseTypes.contains(AuthParams.ResponseType.code)) {
uri.queryParam("code", sessionsRepo.generateAuthorizationCode(sessionId));
}
if (responseTypes.contains(AuthParams.ResponseType.token)) {
uri.queryParam("access_token", session.tokens().accessToken());
}
if (responseTypes.contains(AuthParams.ResponseType.id_token)) {
uri.queryParam("id_token", session.tokens().idToken());
}
return Response.seeOther(uri.build()).build();
} }
@POST @POST

View File

@@ -6,6 +6,12 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
public class AuthParams { public class AuthParams {
public List<ResponseType> getResponseTypes() {
return responseType == null ? List.of() : Arrays.stream(responseType.split(" "))
.map(ResponseType::valueOf)
.toList();
}
@RestQuery("login_hint") @RestQuery("login_hint")
String loginHint; String loginHint;
@RestQuery("response_type") @RestQuery("response_type")
@@ -31,8 +37,8 @@ public class AuthParams {
return responseType; return responseType;
} }
public void setResponseType(String responseType) { public enum ResponseType {
this.responseType = responseType; code, token, id_token
} }
public String getClientId() { public String getClientId() {

View File

@@ -1,18 +1,36 @@
package com.ysoft.geecon.dto; package com.ysoft.geecon.dto;
import com.ysoft.geecon.repo.SecureRandomStrings;
import java.util.List; import java.util.List;
public record AuthorizationSession(AuthParams params, OAuthClient client, User user, List<String> acceptedScopes) { public record AuthorizationSession(AuthParams params,
OAuthClient client,
User user,
List<String> acceptedScopes,
AccessTokenResponse tokens) {
public AuthorizationSession(AuthParams params, OAuthClient client) { public AuthorizationSession(AuthParams params, OAuthClient client) {
this(params, client, null, null); this(params, client, null, null, null);
} }
public AuthorizationSession withUser(User user) { public AuthorizationSession withUser(User user) {
return new AuthorizationSession(params, client, user, acceptedScopes); return new AuthorizationSession(params, client, user, acceptedScopes, tokens);
} }
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, tokens);
}
public AuthorizationSession withGeneratedTokens() {
String idToken = null;
var tokens = new AccessTokenResponse("Bearer",
8400,
SecureRandomStrings.alphanumeric(50),
scope(),
SecureRandomStrings.alphanumeric(50),
idToken
);
return new AuthorizationSession(params, client, user, acceptedScopes, tokens);
} }
public String scope() { public String scope() {

View File

@@ -1,6 +1,9 @@
package com.ysoft.geecon.repo; package com.ysoft.geecon.repo;
import com.ysoft.geecon.dto.*; import com.ysoft.geecon.dto.AuthParams;
import com.ysoft.geecon.dto.AuthorizationSession;
import com.ysoft.geecon.dto.OAuthClient;
import com.ysoft.geecon.dto.User;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import java.util.*; import java.util.*;
@@ -20,11 +23,9 @@ public class SessionsRepo {
return id; return id;
} }
public String finishSession(String sessionId, List<String> acceptedScopes) { public AuthorizationSession authorizeSession(String sessionId, List<String> acceptedScopes) {
Objects.requireNonNull(authorizationSessions.computeIfPresent(sessionId, (id, s) -> s.withScopes(acceptedScopes))); return Objects.requireNonNull(authorizationSessions.computeIfPresent(sessionId,
var authCode = SecureRandomStrings.alphanumeric(10); (id, s) -> s.withScopes(acceptedScopes).withGeneratedTokens()));
sessionsByAuthorizationCode.put(authCode, sessionId);
return authCode;
} }
@@ -32,6 +33,12 @@ public class SessionsRepo {
return Objects.requireNonNull(authorizationSessions.computeIfPresent(sessionId, (id, session) -> session.withUser(user))); return Objects.requireNonNull(authorizationSessions.computeIfPresent(sessionId, (id, session) -> session.withUser(user)));
} }
public String generateAuthorizationCode(String sessionId) {
var authCode = SecureRandomStrings.alphanumeric(10);
sessionsByAuthorizationCode.put(authCode, sessionId);
return authCode;
}
public Optional<AuthorizationSession> redeemAuthorizationCode(String authorizationCode) { public Optional<AuthorizationSession> redeemAuthorizationCode(String authorizationCode) {
var sessionId = Optional.ofNullable(sessionsByAuthorizationCode.get(authorizationCode)); var sessionId = Optional.ofNullable(sessionsByAuthorizationCode.get(authorizationCode));
sessionId.ifPresent(_id -> sessionsByAuthorizationCode.remove(authorizationCode)); sessionId.ifPresent(_id -> sessionsByAuthorizationCode.remove(authorizationCode));