Skip to content

Commit

Permalink
Quickstart content recomposed as a tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
sheilamjones committed Jan 26, 2023
1 parent a7da163 commit 22f8e11
Show file tree
Hide file tree
Showing 13 changed files with 370 additions and 333 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ For more information about OIDC authentication and authorization methods you can
|====
|OIDC topic |Quarkus information resource
|Bearer Token authentication mechanism|xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication]
|Authorization Code Flow authentication mechanism|xref:security-openid-connect-web-authentication.adoc[OpenID Connect (OIDC) authorization code flow mechanism]
|Authorization Code Flow authentication mechanism|xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow]
|Multiple tenants that can support Bearer Token or Authorization Code Flow mechanisms|xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect (OIDC) multi-tenancy]
|Using Keycloak to centralize authorization|xref:security-keycloak-authorization.adoc[Using OpenID Connect (OIDC) and Keycloak to centralize authorization]
|Configuring Keycloak programmatically|xref:security-keycloak-admin-client.adoc[Using the Keycloak admin client]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,14 +589,12 @@ After you have completed this tutorial, explore some of the more advanced securi
Use the following information to learn how you can securely use `OpenID Connect` to provide secure single sign-on access to your Quarkus endpoints:

* xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication]
* xref:security-openid-connect-web-authentication.adoc[Using OpenID Connect (OIDC) to Protect Web Applications using Authorization Code Flow
]
* xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow]

== References

* xref:security-overview-concept.adoc[Quarkus Security overview]
* xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication]
* xref:security-openid-connect-web-authentication.adoc[Using OpenID Connect (OIDC) to Protect Web Applications using Authorization Code Flow
]
* xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow]
* xref:hibernate-orm-panache.adoc[Simplified Hibernate ORM with Panache]
* xref:hibernate-orm.adoc[Using Hibernate ORM and JPA]
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-jwt.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ to verify https://tools.ietf.org/html/rfc7519[JSON Web Token]s, represent them a
and provide secured access to the Quarkus HTTP endpoints using Bearer Token Authorization and https://en.wikipedia.org/wiki/Role-based_access_control[Role-Based Access Control].

NOTE: Quarkus OpenID Connect `quarkus-oidc` extension also supports Bearer Token Authorization and uses `smallrye-jwt` to represent the bearer tokens as `JsonWebToken`, please read the xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication] guide for more information.
OpenID Connect extension has to be used if the Quarkus application needs to authenticate the users using OIDC Authorization Code Flow, please read xref:security-openid-connect-web-authentication.adoc[Using OpenID Connect to Protect Web Applications] guide for more information.
OpenID Connect extension has to be used if the Quarkus application needs to authenticate the users using OIDC Authorization Code Flow. For more information, see xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow].

== Prerequisites

Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-keycloak-admin-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ include::{generated-dir}/config/quarkus-keycloak-admin-client.adoc[leveloffset=+

* https://www.keycloak.org/documentation.html[Keycloak Documentation]
* xref:security-keycloak-authorization.adoc[Keycloak Authorization extension]
* xref:security-openid-connect-web-authentication.adoc[Using OpenID Connect to Protect Web Application]
* xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow]
* xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication]
* xref:security-openid-connect-client.adoc[OpenID Connect Client and Token Propagation Quickstart]
* xref:security-overview-concept.adoc[Quarkus Security overview]
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-oauth2.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ It can be used to implement an application authentication mechanism based on tok
This extension provides a light-weight support for using the opaque Bearer Tokens and validating them by calling an introspection endpoint.

If the OAuth2 Authentication server provides JWT Bearer Tokens then you should consider using either xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication] or xref:security-jwt.adoc[SmallRye JWT] extensions instead.
OpenID Connect extension has to be used if the Quarkus application needs to authenticate the users using OIDC Authorization Code Flow, please read xref:security-openid-connect-web-authentication.adoc[Using OpenID Connect to Protect Web Applications] guide for more information.
OpenID Connect extension has to be used if the Quarkus application needs to authenticate the users using OIDC Authorization Code Flow. For more information, see the xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow] guide.

include::{includes}/extension-status.adoc[]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ image::security-bearer-token-authorization-mechanism-2.png[alt=Bearer authentica
3. The Client uses the access token to retrieve the service data from the Quarkus service.
4. The Quarkus service verifies the bearer access token signature using the verification keys, checks the token expiry date and other claims, allows the request to proceed if the token is valid, and returns the service response to the Client.

If you need to authenticate and authorize the users using OpenID Connect Authorization Code Flow, see xref:security-openid-connect-web-authentication.adoc[Using OpenID Connect to Protect Web Applications].
If you need to authenticate and authorize the users using OpenID Connect Authorization Code Flow, see xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow].
Also, if you use Keycloak and bearer tokens, see xref:security-keycloak-authorization.adoc[Using Keycloak to Centralize Authorization].

For information about how to support multiple tenants, see xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect Multi-Tenancy].
Expand Down Expand Up @@ -314,7 +314,7 @@ Please see xref:security-openid-connect-client-reference.adoc#token-propagation[
[[oidc-provider-authentication]]
=== Oidc Provider Client Authentication

`quarkus.oidc.runtime.OidcProviderClient` is used when a remote request to an OpenID Connect Provider has to be done. If the bearer token has to be introspected then `OidcProviderClient` has to authenticate to the OpenID Connect Provider. Please see xref:security-openid-connect-web-authentication.adoc#oidc-provider-client-authentication[OidcProviderClient Authentication] for more information about all the supported authentication options.
`quarkus.oidc.runtime.OidcProviderClient` is used when a remote request to an OpenID Connect Provider has to be done. If the bearer token has to be introspected then `OidcProviderClient` has to authenticate to the OpenID Connect Provider. Please see xref:security-oidc-web-authentication-concept#oidc-provider-client-authentication[OidcProviderClient Authentication] for more information about all the supported authentication options.

[[integration-testing]]
=== Testing
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
[id="security-oidc-protect-web-application-tutorial"]
= Protect a web application by using OIDC authorization code flow mechanism
include::_attributes.adoc[]
:categories: security,web

With the Quarkus OpenID Connect (OIDC) extension, you can protect application HTTP endpoints by using the OIDC Authorization Code Flow mechanism.

To learn more about the OIDC authorization code flow mechanism, see xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow] or to learn about other authentication mechanisms, see xref:security-authentication-mechanisms-concept.adoc#other-supported-authentication-mechanisms[authentication mechanisms].

== Prerequisites

:prerequisites-docker:
include::{includes}/prerequisites.adoc[]

== Architecture

In this example, we build a very simple web application with a single page:

* `/index.html`

This page is protected and can only be accessed by authenticated users.

== Solution

We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone {quickstarts-clone-url}`, or download an {quickstarts-archive-url}[archive].

The solution is located in the `security-openid-connect-web-authentication-quickstart` {quickstarts-tree-url}/security-openid-connect-web-authentication-quickstart[directory].

== Procedure

=== Create the Maven project

First, we need a new project.
Create a new project with the following command:

:create-app-artifact-id: security-openid-connect-web-authentication-quickstart
:create-app-extensions: resteasy-reactive,oidc
include::{includes}/devtools/create-app.adoc[]

If you already have your Quarkus project configured, you can add the `oidc` extension to your project by running the following command in your project base directory:

:add-extension-extensions: oidc
include::{includes}/devtools/extension-add.adoc[]

This will add the following to your build file:

[source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"]
.pom.xml
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
----

[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"]
.build.gradle
----
implementation("io.quarkus:quarkus-oidc")
----

=== Write the application

Let's write a simple JAX-RS resource which has all the tokens returned in the authorization code grant response injected:

[source,java]
----
package org.acme.security.openid.connect.web.authentication;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.eclipse.microprofile.jwt.JsonWebToken;
import io.quarkus.oidc.IdToken;
import io.quarkus.oidc.RefreshToken;
@Path("/tokens")
public class TokenResource {
/**
* Injection point for the ID Token issued by the OpenID Connect Provider
*/
@Inject
@IdToken
JsonWebToken idToken;
/**
* Injection point for the Access Token issued by the OpenID Connect Provider
*/
@Inject
JsonWebToken accessToken;
/**
* Injection point for the Refresh Token issued by the OpenID Connect Provider
*/
@Inject
RefreshToken refreshToken;
/**
* Returns the tokens available to the application. This endpoint exists only for demonstration purposes, you should not
* expose these tokens in a real application.
*
* @return a HTML page containing the tokens available to the application
*/
@GET
@Produces("text/html")
public String getTokens() {
StringBuilder response = new StringBuilder().append("<html>")
.append("<body>")
.append("<ul>");
Object userName = this.idToken.getClaim("preferred_username");
if (userName != null) {
response.append("<li>username: ").append(userName.toString()).append("</li>");
}
Object scopes = this.accessToken.getClaim("scope");
if (scopes != null) {
response.append("<li>scopes: ").append(scopes.toString()).append("</li>");
}
response.append("<li>refresh_token: ").append(refreshToken.getToken() != null).append("</li>");
return response.append("</ul>").append("</body>").append("</html>").toString();
}
}
----

This endpoint has ID, access, and refresh tokens injected.
It returns a `preferred_username` claim from the ID token, a `scope` claim from the access token, and also a refresh token availability status.

Note that you do not have to inject the tokens - it is only required if the endpoint needs to use the ID token to interact with the currently authenticated user or use the access token to access a downstream service on behalf of this user.

// SJ: TO DO - update link to point to new reference guide. For more information, see <<access_id_and_access_tokens,Access ID and Access Tokens>> section.

=== Configure the application

The OIDC extension allows you to define the configuration using the `application.properties` file which should be located at the `src/main/resources` directory.

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/realms/quarkus
quarkus.oidc.client-id=frontend
quarkus.oidc.credentials.secret=secret
quarkus.oidc.application-type=web-app
quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated
----

This is the simplest configuration you can have when enabling authentication to your application.

The `quarkus.oidc.client-id` property references the `client_id` issued by the OIDC provider and the `quarkus.oidc.credentials.secret` property sets the client secret.

The `quarkus.oidc.application-type` property is set to `web-app` in order to tell Quarkus that you want to enable the OIDC authorization code flow, so that your users are redirected to the OIDC provider to authenticate.

Finally, the `quarkus.http.auth.permission.authenticated` permission is set to tell Quarkus about the paths you want to protect.
In this case, all paths are being protected by a policy that ensures that only `authenticated` users are allowed to access.
For more information, see xref:security-authorization-of-web-endpoints-reference.adoc[Security Authorization Guide].

=== Start and configure the Keycloak server

To start a Keycloak server, use Docker and run the following command:

[source,bash,subs=attributes+]
----
docker run --name keycloak -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -p 8180:8080 quay.io/keycloak/keycloak:{keycloak.version} start-dev
----

where `keycloak.version` should be set to `17.0.0` or higher.

You should be able to access your Keycloak Server at http://localhost:8180[localhost:8180].

To access the Keycloak Administration Console, log in as the `admin` user.
Username should be `admin` and password `admin`.

Import the {quickstarts-tree-url}/security-openid-connect-web-authentication-quickstart/config/quarkus-realm.json[realm configuration file] to create a new realm.
For more information, see the Keycloak documentation about how to https://www.keycloak.org/docs/latest/server_admin/index.html#_create-realm[create a new realm].

=== Run the application in dev and JVM modes

To run the application in a dev mode, use:

include::{includes}/devtools/dev.adoc[]

When you're done playing with dev mode, you can run it as a standard Java application.

First, compile it:

include::{includes}/devtools/build.adoc[]

Then, run it:

[source,bash]
----
java -jar target/quarkus-app/quarkus-run.jar
----

=== Run the application in Native mode

This same demo can be compiled into native code.
No modifications are required.

This implies that you no longer need to install a JVM on your production environment, as the runtime technology is included in
the produced binary, and optimized to run with minimal resource overhead.

Compilation will take a bit longer, so this step is disabled by default.
You can build again by enabling the native build:

include::{includes}/devtools/build-native.adoc[]

After getting a cup of coffee, you can run this binary directly:

[source,bash]
----
./target/security-openid-connect-web-authentication-quickstart-runner
----

=== Test the application

To test the application, open your browser and access the following URL:


* http://localhost:8080/tokens[http://localhost:8080/tokens]

If everything is working as expected, you are redirected to the Keycloak server to authenticate.

To authenticate to the application, type the following credentials when at the Keycloak login page:

* Username: *alice*
* Password: *alice*

After clicking the `Login` button, you are redirected back to the application.

For more information about writing the integration tests that depend on `Dev Services for Keycloak`, see the <<integration-testing-keycloak-devservices, Dev Services for Keycloak>> section.

== Summary

Congratulations!
You have learned how to set up and use the OIDC authorization code flow mechanism to protect and test application HTTP endpoints.
After you have completed this tutorial, explore some of the other security mechanisms in Quarkus.

* xref:security-oidc-bearer-authentication-concept.adoc[OIDC Bearer authentication]
* xref:security-overview-concept.adoc[Quarkus Security overview]


== References
* xref:security-oidc-web-authentication-concept.adoc[Web authentication using OIDC authorization code flow]
* https://www.keycloak.org/documentation.html[Keycloak Documentation]
* https://openid.net/connect/[OpenID Connect]
* https://tools.ietf.org/html/rfc7519[JSON Web Token]
* xref:security-openid-connect-client-reference.adoc[OpenID Connect and OAuth2 Client and Filters Reference Guide]
* xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak]
* xref:security-jwt-build.adoc[Sign and encrypt JWT tokens with SmallRye JWT Build]
* xref:security-authentication-mechanisms-concept.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms]
* xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client]

0 comments on commit 22f8e11

Please sign in to comment.