Skip to content

Commit

Permalink
Get all code flow credentials visible to SecurityIdentityAugmentors
Browse files Browse the repository at this point in the history
  • Loading branch information
sberyozkin committed Aug 23, 2021
1 parent 1229189 commit 9541ae2
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import static io.quarkus.oidc.runtime.OidcIdentityProvider.REFRESH_TOKEN_GRANT_RESPONSE;

import java.net.URI;
import java.security.Permission;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand All @@ -19,12 +18,10 @@
import org.jose4j.jwt.consumer.InvalidJwtException;

import io.netty.handler.codec.http.HttpResponseStatus;
import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.AuthorizationCodeTokens;
import io.quarkus.oidc.IdTokenCredential;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.OidcTenantConfig.Authentication;
import io.quarkus.oidc.RefreshToken;
import io.quarkus.oidc.SecurityEvent;
import io.quarkus.oidc.common.runtime.OidcCommonUtils;
import io.quarkus.oidc.common.runtime.OidcConstants;
Expand All @@ -33,7 +30,6 @@
import io.quarkus.security.AuthenticationRedirectException;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
import io.smallrye.mutiny.Uni;
import io.vertx.core.http.Cookie;
Expand All @@ -57,27 +53,6 @@ public class CodeAuthenticationMechanism extends AbstractOidcAuthenticationMecha
private static final String STATE_COOKIE_NAME = "q_auth";
private static final String POST_LOGOUT_COOKIE_NAME = "q_post_logout";

private static QuarkusSecurityIdentity augmentIdentity(SecurityIdentity securityIdentity,
String accessToken,
String refreshToken,
RoutingContext context) {
IdTokenCredential idTokenCredential = securityIdentity.getCredential(IdTokenCredential.class);
RefreshToken refreshTokenCredential = new RefreshToken(refreshToken);
return QuarkusSecurityIdentity.builder()
.setPrincipal(securityIdentity.getPrincipal())
.addCredential(idTokenCredential)
.addCredential(new AccessTokenCredential(accessToken, refreshTokenCredential, context))
.addCredential(refreshTokenCredential)
.addRoles(securityIdentity.getRoles())
.addAttributes(securityIdentity.getAttributes())
.addPermissionChecker(new Function<Permission, Uni<Boolean>>() {
@Override
public Uni<Boolean> apply(Permission permission) {
return securityIdentity.checkPermission(permission);
}
}).build();
}

public Uni<SecurityIdentity> authenticate(RoutingContext context,
IdentityProviderManager identityProviderManager) {
return resolver.resolveConfig(context).chain(new Function<OidcTenantConfig, Uni<? extends SecurityIdentity>>() {
Expand Down Expand Up @@ -125,6 +100,7 @@ private Uni<SecurityIdentity> reAuthenticate(Cookie sessionCookie,
sessionCookie.getValue());

context.put(OidcConstants.ACCESS_TOKEN_VALUE, session.getAccessToken());
context.put(AuthorizationCodeTokens.class.getName(), session);
return authenticate(identityProviderManager, context, new IdTokenCredential(session.getIdToken(), context))
.map(new Function<SecurityIdentity, SecurityIdentity>() {
@Override
Expand All @@ -133,8 +109,7 @@ public SecurityIdentity apply(SecurityIdentity identity) {
fireEvent(SecurityEvent.Type.OIDC_LOGOUT_RP_INITIATED, identity);
throw redirectToLogoutEndpoint(context, configContext, session.getIdToken());
}

return augmentIdentity(identity, session.getAccessToken(), session.getRefreshToken(), context);
return identity;
}
}).onFailure().recoverWithUni(new Function<Throwable, Uni<? extends SecurityIdentity>>() {
@Override
Expand Down Expand Up @@ -299,6 +274,7 @@ public Uni<SecurityIdentity> apply(final AuthorizationCodeTokens tokens, final T

context.put(NEW_AUTHENTICATION, Boolean.TRUE);
context.put(OidcConstants.ACCESS_TOKEN_VALUE, tokens.getAccessToken());
context.put(AuthorizationCodeTokens.class.getName(), tokens);

return authenticate(identityProviderManager, context,
new IdTokenCredential(tokens.getIdToken(), context))
Expand Down Expand Up @@ -332,8 +308,7 @@ public SecurityIdentity apply(SecurityIdentity identity) {
LOG.debugf("Final redirect URI: %s", finalRedirectUri);
throw new AuthenticationRedirectException(finalRedirectUri);
} else {
return augmentIdentity(identity, tokens.getAccessToken(),
tokens.getRefreshToken(), context);
return identity;
}
}
}).onFailure().transform(new Function<Throwable, Throwable>() {
Expand Down Expand Up @@ -520,6 +495,7 @@ public Uni<SecurityIdentity> apply(final AuthorizationCodeTokens tokens, final T
}
} else {
context.put(OidcConstants.ACCESS_TOKEN_VALUE, tokens.getAccessToken());
context.put(AuthorizationCodeTokens.class.getName(), tokens);
context.put(REFRESH_TOKEN_GRANT_RESPONSE, Boolean.TRUE);

return authenticate(identityProviderManager, context,
Expand All @@ -530,14 +506,11 @@ public SecurityIdentity apply(SecurityIdentity identity) {
// after a successful refresh, rebuild the identity and update the cookie
processSuccessfulAuthentication(context, configContext,
tokens, identity);
SecurityIdentity newSecurityIdentity = augmentIdentity(identity,
tokens.getAccessToken(), tokens.getRefreshToken(), context);

fireEvent(autoRefresh ? SecurityEvent.Type.OIDC_SESSION_REFRESHED
: SecurityEvent.Type.OIDC_SESSION_EXPIRED_AND_REFRESHED,
newSecurityIdentity);
identity);

return newSecurityIdentity;
return identity;
}
}).onFailure().transform(new Function<Throwable, Throwable>() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;

import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.AuthorizationCodeTokens;
import io.quarkus.oidc.OIDCException;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.RefreshToken;
import io.quarkus.oidc.TokenIntrospection;
import io.quarkus.oidc.UserInfo;
import io.quarkus.security.AuthenticationFailedException;
Expand Down Expand Up @@ -144,7 +147,13 @@ static QuarkusSecurityIdentity validateAndCreateIdentity(
OidcTenantConfig config = resolvedContext.oidcConfig;
QuarkusSecurityIdentity.Builder builder = QuarkusSecurityIdentity.builder();
builder.addCredential(credential);

AuthorizationCodeTokens codeTokens = vertxContext != null ? vertxContext.get(AuthorizationCodeTokens.class.getName())
: null;
if (codeTokens != null) {
RefreshToken refreshTokenCredential = new RefreshToken(codeTokens.getRefreshToken());
builder.addCredential(refreshTokenCredential);
builder.addCredential(new AccessTokenCredential(codeTokens.getAccessToken(), refreshTokenCredential, vertxContext));
}
JsonWebToken jwtPrincipal;
try {
JwtClaims jwtClaims = JwtClaims.parse(tokenJson.encode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import javax.enterprise.context.ApplicationScoped;

import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.IdTokenCredential;
import io.quarkus.oidc.common.runtime.OidcConstants;
import io.quarkus.security.identity.AuthenticationRequestContext;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.identity.SecurityIdentityAugmentor;
Expand All @@ -24,6 +26,8 @@ public Uni<SecurityIdentity> augment(SecurityIdentity identity, AuthenticationRe
if (cred != null) {
QuarkusSecurityIdentity.Builder builder = QuarkusSecurityIdentity.builder(identity);
builder.addAttribute(RoutingContext.class.getName(), cred.getRoutingContext());
builder.addAttribute(OidcConstants.ACCESS_TOKEN_VALUE,
identity.getCredential(AccessTokenCredential.class).getToken());
identity = builder.build();
}
return Uni.createFrom().item(identity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.quarkus.oidc.OidcConfigurationMetadata;
import io.quarkus.oidc.RefreshToken;
import io.quarkus.oidc.UserInfo;
import io.quarkus.oidc.common.runtime.OidcConstants;
import io.quarkus.security.Authenticated;
import io.quarkus.security.identity.SecurityIdentity;
import io.vertx.ext.web.RoutingContext;
Expand Down Expand Up @@ -168,9 +169,12 @@ public String getTenantLogout() {
@GET
@Path("access")
public String getAccessToken() {
if (accessToken.getRawToken() != null && !accessTokenCredential.getToken().equals(accessToken.getRawToken())) {
if (accessToken.getRawToken() != null &&
(!accessTokenCredential.getToken().equals(accessToken.getRawToken())
|| !identity.getAttribute(OidcConstants.ACCESS_TOKEN_VALUE).equals(accessToken.getRawToken()))) {
throw new OIDCException("Access token values are not equal");
}

return accessToken.getRawToken() != null && !accessToken.getRawToken().isEmpty() ? "AT injected" : "no access";
}

Expand Down

0 comments on commit 9541ae2

Please sign in to comment.