Skip to content

Commit

Permalink
Merge pull request quarkusio#36361 from sberyozkin/fix_oidc_scope_to_…
Browse files Browse the repository at this point in the history
…permission_conversion

Check semicolon during the OIDC scope to permission conversion
  • Loading branch information
sberyozkin authored Oct 9, 2023
2 parents ea956d0 + ded3836 commit 2700890
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,17 @@ public Uni<Boolean> apply(Permission requiredPermission) {
}
}

private static Permission[] transformScopesToPermissions(Collection<String> scopes) {
static Permission[] transformScopesToPermissions(Collection<String> scopes) {
final Permission[] permissions = new Permission[scopes.size()];
int i = 0;
for (String scope : scopes) {
permissions[i++] = new StringPermission(scope);
int semicolonIndex = scope.indexOf(':');
if (semicolonIndex > 0 && semicolonIndex < scope.length() - 1) {
permissions[i++] = new StringPermission(scope.substring(0, semicolonIndex),
scope.substring(semicolonIndex + 1));
} else {
permissions[i++] = new StringPermission(scope);
}
}
return permissions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.Permission;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -664,6 +665,22 @@ public void testDecodeJwt() throws Exception {
assertTrue(json.containsKey("jti"));
}

@Test
public void testTransformScopeToPermission() throws Exception {
Permission[] perms = OidcUtils.transformScopesToPermissions(
List.of("read", "read:d", "read:", ":read"));
assertEquals(4, perms.length);

assertEquals("read", perms[0].getName());
assertNull(perms[0].getActions());
assertEquals("read", perms[1].getName());
assertEquals("d", perms[1].getActions());
assertEquals("read:", perms[2].getName());
assertNull(perms[2].getActions());
assertEquals(":read", perms[3].getName());
assertNull(perms[3].getActions());
}

public static JsonObject read(InputStream input) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
return new JsonObject(buffer.lines().collect(Collectors.joining("\n")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.eclipse.microprofile.jwt.JsonWebToken;

import io.quarkus.security.Authenticated;
import io.quarkus.security.PermissionsAllowed;

@Path("/service/tenant-public-key")
@Authenticated
Expand All @@ -16,6 +17,7 @@ public class ServiceProtectedResource {
JsonWebToken accessToken;

@GET
@PermissionsAllowed("read:data")
public String getName() {
return "tenant-public-key" + ":" + accessToken.getName();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.quarkus.it.keycloak;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.IOException;
import java.time.Instant;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;
Expand All @@ -15,21 +16,28 @@
public class ServicePublicKeyTestCase {

@Test
public void testAccessTokenInjection() throws IOException, InterruptedException {
String jwt = Jwt.claims().preferredUserName("alice").sign();
Assertions.assertEquals("tenant-public-key:alice", RestAssured.given().auth()
public void testAccessTokenInjection() {
String jwt = Jwt.claim("scope", "read:data").preferredUserName("alice").sign();
assertEquals("tenant-public-key:alice", RestAssured.given().auth()
.oauth2(jwt)
.get("/service/tenant-public-key").getBody().asString());
}

@Test
public void testModifiedSignature() throws IOException, InterruptedException {
public void testAccessTokenInjection403() {
String jwt = Jwt.claim("scope", "read:doc").preferredUserName("alice").sign();
RestAssured.given().auth().oauth2(jwt)
.get("/service/tenant-public-key").then().statusCode(403);
}

@Test
public void testModifiedSignature() {
String jwt = Jwt.claims().preferredUserName("alice").sign();
// the last section of the jwt token is a signature
Response r = RestAssured.given().auth()
.oauth2(jwt + "1")
.get("/service/tenant-public-key");
Assertions.assertEquals(401, r.getStatusCode());
assertEquals(401, r.getStatusCode());
}

@Test
Expand All @@ -39,6 +47,6 @@ public void testExpiredToken() throws IOException, InterruptedException {
Response r = RestAssured.given().auth()
.oauth2(jwt)
.get("/service/tenant-public-key");
Assertions.assertEquals(401, r.getStatusCode());
assertEquals(401, r.getStatusCode());
}
}

0 comments on commit 2700890

Please sign in to comment.