Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check semicolon during the OIDC scope to permission conversion #36361

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
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());
}
}
Loading