Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.quarkus.oidc;

import io.quarkus.security.credential.TokenCredential;

public class AccessTokenCredential extends TokenCredential {

private String refreshToken;

/**
* Create AccessTokenCredential
*
* @param accessToken - access token
*/
public AccessTokenCredential(String accessToken) {
this(accessToken, null);
}

/**
* Create AccessTokenCredential
*
* @param accessToken - access token
* @param refreshToken - refresh token which can be used to refresh this access token, may be null
*/
public AccessTokenCredential(String accessToken, String refreshToken) {
super(accessToken, "bearer");
if (accessToken.equals(refreshToken)) {
throw new OIDCException("Access and refresh tokens can not be equal");
}
this.refreshToken = refreshToken;
}

public String getRefreshToken() {
return refreshToken;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.oidc.runtime;
package io.quarkus.oidc;

import io.quarkus.security.credential.TokenCredential;

Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.enterprise.context.ApplicationScoped;

import io.netty.handler.codec.http.HttpResponseStatus;
import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import javax.enterprise.context.ApplicationScoped;

import io.netty.handler.codec.http.HttpResponseStatus;
import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.IdTokenCredential;
import io.quarkus.security.AuthenticationFailedException;
import io.quarkus.security.identity.IdentityProviderManager;
import io.quarkus.security.identity.SecurityIdentity;
Expand All @@ -38,8 +40,7 @@ private static QuarkusSecurityIdentity augmentIdentity(SecurityIdentity security
return QuarkusSecurityIdentity.builder()
.setPrincipal(securityIdentity.getPrincipal())
.addCredentials(securityIdentity.getCredentials())
.addCredential(new AccessTokenCredential(accessToken))
.addCredential(new RefreshToken(refreshToken))
.addCredential(new AccessTokenCredential(accessToken, refreshToken))
.addRoles(securityIdentity.getRoles())
.addAttributes(securityIdentity.getAttributes())
.addPermissionChecker(new Function<Permission, CompletionStage<Boolean>>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
import javax.enterprise.inject.Produces;
import javax.inject.Inject;

import org.eclipse.microprofile.jwt.Claims;
import org.eclipse.microprofile.jwt.JsonWebToken;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.IdToken;
import io.quarkus.oidc.IdTokenCredential;
import io.quarkus.security.credential.TokenCredential;
import io.quarkus.security.identity.SecurityIdentity;
import io.smallrye.jwt.auth.cdi.NullJsonWebToken;
Expand Down Expand Up @@ -47,17 +50,6 @@ JsonWebToken currentIdToken() {
return getTokenCredential(IdTokenCredential.class);
}

/**
* The producer method for the current id token
*
* @return the id token
*/
@Produces
@RequestScoped
RefreshToken currentRefreshToken() {
return identity.getCredential(RefreshToken.class);
}

private JsonWebToken getTokenCredential(Class<? extends TokenCredential> type) {
if (identity.isAnonymous()) {
return new NullJsonWebToken();
Expand All @@ -73,6 +65,7 @@ private JsonWebToken getTokenCredential(Class<? extends TokenCredential> type) {
} catch (InvalidJwtException e) {
throw new RuntimeException(e);
}
jwtClaims.setClaim(Claims.raw_token.name(), credential.getToken());
return new OidcJwtCallerPrincipal(jwtClaims);
}
throw new IllegalStateException("Current identity not associated with an access token");
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.IdToken;
import io.quarkus.oidc.runtime.RefreshToken;
import io.quarkus.security.identity.SecurityIdentity;

@Path("/web-app")
public class ProtectedResource {
Expand All @@ -17,16 +18,27 @@ public class ProtectedResource {
JsonWebToken idToken;

@Inject
RefreshToken refreshToken;
JsonWebToken accessToken;

@Inject
SecurityIdentity identity;

@GET
public String getName() {
return idToken.getName();
}

@GET
public String get() {
return idToken.getClaim("preferred_username");
@Path("access")
public String getAccessToken() {
return accessToken.getRawToken() != null && !accessToken.getRawToken().isEmpty() ? "AT injected" : "";
// or get it with identity.getCredential(AccessTokenCredential.class).getToken();
}

@GET
@Path("refresh")
public String refresh() {
return refreshToken.getToken() != null ? "injected" : null;
String refreshToken = identity.getCredential(AccessTokenCredential.class).getRefreshToken();
return refreshToken != null && !refreshToken.isEmpty() ? "RT injected" : "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,30 @@ public void testIdTokenInjection() throws IOException, InterruptedException {
}

@Test
public void testRefreshTokenInjection() throws IOException, InterruptedException {
//@Disabled
public void testAccessTokenInjection() throws IOException, InterruptedException {
try (final WebClient webClient = new WebClient()) {
HtmlPage page = webClient.getPage("http://localhost:8081/index.html");

assertEquals("Log in to quarkus", page.getTitleText());

HtmlForm loginForm = page.getForms().get(0);

loginForm.getInputByName("username").setValueAttribute("alice");
loginForm.getInputByName("password").setValueAttribute("alice");

page = loginForm.getInputByName("login").click();

assertEquals("Welcome to Test App", page.getTitleText());

page = webClient.getPage("http://localhost:8081/web-app/access");

assertEquals("AT injected", page.getBody().asText());
}
}

@Test
public void testAccessAndRefreshTokenInjection() throws IOException, InterruptedException {
try (final WebClient webClient = new WebClient()) {
HtmlPage page = webClient.getPage("http://localhost:8081/index.html");

Expand All @@ -224,7 +247,7 @@ public void testRefreshTokenInjection() throws IOException, InterruptedException

page = webClient.getPage("http://localhost:8081/web-app/refresh");

assertEquals("injected", page.getBody().asText());
assertEquals("RT injected", page.getBody().asText());
}
}

Expand Down
17 changes: 0 additions & 17 deletions integration-tests/oidc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

<properties>
<keycloak.url>http://localhost:8180/auth</keycloak.url>
<htmlunit.version>2.36.0</htmlunit.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -48,22 +47,6 @@
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>${htmlunit.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
Expand Down