Skip to content

Commit

Permalink
Merge pull request #15965 from sberyozkin/keycloak_authz_permit_for_n…
Browse files Browse the repository at this point in the history
…on_bearer_auth

KeycloakPolicyEnforcerAuthorizer should permit if authentication is not done by OIDC
  • Loading branch information
sberyozkin authored Mar 25, 2021
2 parents ff70524 + 45ddbfa commit 320a632
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ public class PolicyEnforcerTest {
public JavaArchive get() {
return ShrinkWrap.create(JavaArchive.class)
.addAsResource("application.properties")
.addClasses(ProtectedResource.class, PublicResource.class, UsersResource.class);
.addClasses(ProtectedResource.class, ProtectedResource2.class, PublicResource.class,
UsersResource.class);
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.keycloak.pep.test;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

import io.quarkus.security.Authenticated;

@Path("/api2/resource")
@Authenticated
public class ProtectedResource2 {

@GET
public String testResource() {
// This method must not be invoked
throw new RuntimeException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,10 @@ quarkus.keycloak.policy-enforcer.paths.3.claim-information-point.http.method=GET
quarkus.keycloak.policy-enforcer.paths.3.claim-information-point.http.headers.Content-Type=application/x-www-form-urlencoded
quarkus.keycloak.policy-enforcer.paths.3.claim-information-point.http.headers.Authorization=Bearer {keycloak.access_token}

# Disables policy enforcement for a path
quarkus.keycloak.policy-enforcer.paths.4.path=/api/public
quarkus.keycloak.policy-enforcer.paths.4.enforcement-mode=DISABLED

# Defines a claim which value is based on the response from an external service
quarkus.keycloak.policy-enforcer.paths.5.path=/api/permission/body-claim
quarkus.keycloak.policy-enforcer.paths.5.claim-information-point.claims.from-body={request.body['/from-body']}

quarkus.keycloak.policy-enforcer.paths.6.name=Root
quarkus.keycloak.policy-enforcer.paths.6.path=/*
quarkus.keycloak.policy-enforcer.paths.6.enforcement-mode=DISABLED

quarkus.keycloak.policy-enforcer.paths.7.name=API
quarkus.keycloak.policy-enforcer.paths.7.path=/api2/*
quarkus.keycloak.policy-enforcer.paths.7.enforcement-mode=ENFORCING

quarkus.keycloak.policy-enforcer.paths.8.name=Public
quarkus.keycloak.policy-enforcer.paths.8.path=/hello
quarkus.keycloak.policy-enforcer.paths.8.enforcement-mode=DISABLED

quarkus.keycloak.policy-enforcer.paths.health.name=Health-check
quarkus.keycloak.policy-enforcer.paths.health.path=/health/*
quarkus.keycloak.policy-enforcer.paths.health.enforcement-mode=DISABLED

quarkus.keycloak.policy-enforcer.paths.6.enforcement-mode=DISABLED
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;

import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.common.runtime.OidcCommonConfig.Tls.Verification;
import io.quarkus.security.identity.SecurityIdentity;
Expand All @@ -43,7 +44,17 @@ public Uni<CheckResult> checkPermission(RoutingContext request, Uni<SecurityIden

@Override
public CheckResult apply(RoutingContext routingContext, SecurityIdentity identity) {
VertxHttpFacade httpFacade = new VertxHttpFacade(routingContext,

AccessTokenCredential credential = identity.getCredential(AccessTokenCredential.class);

if (credential == null) {
// If SecurityIdentity has been created by the authentication mechanism other than quarkus-oidc then do not block
// the request.
return CheckResult.PERMIT;
}

String token = credential.getToken();
VertxHttpFacade httpFacade = new VertxHttpFacade(routingContext, token,
configBean.httpConfiguration.readTimeout.toMillis());
AuthorizationContext result = delegate.authorize(httpFacade);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@
import org.keycloak.representations.AccessToken;

import io.netty.handler.codec.http.HttpHeaderNames;
import io.quarkus.oidc.AccessTokenCredential;
import io.quarkus.security.credential.TokenCredential;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.vertx.http.runtime.VertxInputStream;
import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
Expand All @@ -35,13 +31,15 @@ public class VertxHttpFacade implements OIDCHttpFacade {
private final Response response;
private final RoutingContext routingContext;
private final Request request;
private final String token;
private final long readTimeout;

public VertxHttpFacade(RoutingContext routingContext, long readTimeout) {
public VertxHttpFacade(RoutingContext routingContext, String token, long readTimeout) {
this.routingContext = routingContext;
this.token = token;
this.readTimeout = readTimeout;
request = createRequest(routingContext);
response = createResponse(routingContext);
this.request = createRequest(routingContext);
this.response = createResponse(routingContext);
}

@Override
Expand Down Expand Up @@ -222,18 +220,6 @@ public void end() {

@Override
public KeycloakSecurityContext getSecurityContext() {
SecurityIdentity identity = QuarkusHttpUser.getSecurityIdentityBlocking(routingContext, null);
if (identity == null) {
return null;
}
TokenCredential credential = identity.getCredential(AccessTokenCredential.class);

if (credential == null) {
return null;
}

String token = credential.getToken();

try {
return new KeycloakSecurityContext(token, new JWSInput(token).readJsonContent(AccessToken.class), null, null);
} catch (JWSInputException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.it.keycloak;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

import io.quarkus.security.Authenticated;

@Path("/api2/resource")
@Authenticated
public class ProtectedResource2 {

@GET
public String testResource() {
// This method must not be invoked
throw new RuntimeException();
}
}

0 comments on commit 320a632

Please sign in to comment.