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

OIDC: document and use OidcTestClient to get access token from Dev Services for OIDC #45628

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 @@ -857,6 +857,48 @@ For a test like this to work, the test `Auth0` application must have the `passwo
This example code also shows how to pass additional parameters.
For `Auth0`, these are the `audience` and `scope` parameters.

===== Test OIDC DevService

You can also use `OidcTestClient` to test Quarkus endpoints supported by xref:security-openid-connect-dev-services.adoc#dev-services-for-oidc[Dev Services for OIDC].
No configuration in the `application.properties` file is needed, Quarkus will configure `OidcTestClient` for you:

[source, java]
----
package org.acme;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.oidc.client.OidcTestClient;
@QuarkusTest
public class GreetingResourceTest {
static final OidcTestClient oidcTestClient = new OidcTestClient();
@AfterAll
public static void close() {
oidcTestClient.close();
}
@Test
public void testHelloEndpoint() {
String accessToken = oidcTestClient.getAccessToken("alice", "alice");
given()
.auth().oauth2(accessToken)
.when().get("/hello")
.then()
.statusCode(200)
.body(is("Hello, Alice"));
}
}
----

ifndef::no-deprecated-test-resource[]
[[bearer-token-integration-testing-keycloak]]
==== `KeycloakTestResourceLifecycleManager`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ This document refers to the `http://localhost:8080/q/dev-ui` Dev UI URL in sever
If you customize `quarkus.http.root-path` or `quarkus.http.non-application-root-path` properties, then replace `q` accordingly.
For more information, see the https://quarkus.io/blog/path-resolution-in-quarkus/[Path resolution in Quarkus] blog post.

[[dev-services-for-oidc]]
== Dev Services for OIDC

When you work with Keycloak in production, <<dev-services-for-keycloak>> provides the best dev mode experience.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ public interface OidcDevServicesConfig {
/**
* A map of roles for OIDC identity provider users.
* <p>
* If empty, default roles are assigned: `alice` receives `admin` and `user` roles, while other users receive
* `user` role.
* This map is used for role creation when no realm file is found at the `realm-path`.
* If empty, default roles are assigned: user `alice` receives `admin` and `user` roles and user `bob` receives role `user`.
*/
@ConfigDocMapKey("role-name")
Map<String, List<String>> roles();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,6 @@ private static void registerRoutes(Router router) {
router.get("/logout").handler(OidcDevServicesProcessor::logout);
router.get("/userinfo").handler(OidcDevServicesProcessor::userInfo);

// can be used for testing of bearer token authentication
router.get("/testing/generate/access-token").handler(OidcDevServicesProcessor::generateAccessToken);

KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance("RSA");
Expand All @@ -206,22 +203,6 @@ private static void registerRoutes(Router router) {
kid = createKeyId();
}

private static void generateAccessToken(RoutingContext rc) {
String user = rc.request().getParam("user");
if (user == null || user.isEmpty()) {
rc.response().setStatusCode(400).endAndForget("Missing required parameter: user");
return;
}
String rolesParam = rc.request().getParam("roles");
Set<String> roles = new HashSet<>();
if (rolesParam == null || rolesParam.isEmpty()) {
roles.addAll(getUserRoles(user));
} else {
roles.addAll(Arrays.asList(rolesParam.split(",")));
}
rc.response().endAndForget(createAccessToken(user, roles, Set.of("openid", "email")));
}

private static List<String> getUsers() {
if (userToDefaultRoles.isEmpty()) {
return Arrays.asList("alice", "bob");
Expand Down
5 changes: 5 additions & 0 deletions integration-tests/oidc-dev-services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-test-oidc-server</artifactId>
<scope>test</scope>
</dependency>
<!-- Minimal test dependencies to *-deployment artifacts for consistent build order -->
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
quarkus.oidc.devservices.enabled=true
quarkus.oidc.devservices.roles.Ronald=admin

%code-flow.quarkus.oidc.devservices.roles.alice=admin,user
%code-flow.quarkus.oidc.devservices.roles.bob=user
%code-flow.quarkus.oidc.application-type=web-app
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
package io.quarkus.it.oidc.dev.services;

import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.oidc.client.OidcTestClient;
import io.restassured.RestAssured;

@QuarkusTest
public class BearerAuthenticationOidcDevServicesTest {

static final OidcTestClient oidcTestClient = new OidcTestClient();

@AfterAll
public static void close() {
oidcTestClient.close();
}

@Test
public void testLoginAsCustomUser() {
RestAssured.given()
.auth().oauth2(getAccessToken("Ronald", "admin"))
.auth().oauth2(getAccessToken("Ronald"))
.get("/secured/admin-only")
.then()
.statusCode(200)
.body(Matchers.containsString("Ronald"))
.body(Matchers.containsString("admin"));
RestAssured.given()
.auth().oauth2(getAccessToken("Ronald", "admin"))
.auth().oauth2(getAccessToken("Ronald"))
.get("/secured/user-only")
.then()
.statusCode(403);
Expand Down Expand Up @@ -62,16 +71,6 @@ public void testLoginAsBob() {
}

private String getAccessToken(String user) {
return RestAssured.given().get(getAuthServerUrl() + "/testing/generate/access-token?user=" + user).asString();
}

private String getAccessToken(String user, String... roles) {
return RestAssured.given()
.get(getAuthServerUrl() + "/testing/generate/access-token?user=" + user + "&roles=" + String.join(",", roles))
.asString();
}

private static String getAuthServerUrl() {
return RestAssured.get("/secured/auth-server-url").then().statusCode(200).extract().body().asString();
return oidcTestClient.getAccessToken(user, user);
}
}
Loading