diff --git a/docs/src/main/asciidoc/datasource.adoc b/docs/src/main/asciidoc/datasource.adoc index 8c40a26fe3580..9fa2a99b8af5b 100644 --- a/docs/src/main/asciidoc/datasource.adoc +++ b/docs/src/main/asciidoc/datasource.adoc @@ -101,7 +101,9 @@ For more information about pool size adjustment properties, see the <> for suggestions re * MySQL - `quarkus-jdbc-mysql` * Oracle - `quarkus-jdbc-oracle` * PostgreSQL - `quarkus-jdbc-postgresql` +ifndef::no-quarkiverse[] * Other JDBC extensions, such as link:https://github.com/quarkiverse/quarkus-jdbc-sqlite[SQLite] and its link:https://quarkiverse.github.io/quarkiverse-docs/quarkus-jdbc-sqlite/dev/index.html[documentation], can be found in the https://github.com/quarkiverse[Quarkiverse]. +endif::no-quarkiverse[] + For example, to add the PostgreSQL driver dependency: + @@ -302,7 +306,9 @@ Quarkus offers several reactive clients for use with a reactive datasource. . Add the corresponding extension to your application: + +ifndef::no-quarkus-reactive-db2-client[] * DB2: `quarkus-reactive-db2-client` +endif::no-quarkus-reactive-db2-client[] * MariaDB/MySQL: `quarkus-reactive-mysql-client` * Microsoft SQL Server: `quarkus-reactive-mssql-client` * Oracle: `quarkus-reactive-oracle-client` @@ -684,6 +690,7 @@ However, the Quarkus Derby extension allows native compilation of the Derby JDBC * Embedding H2 within your native image is not recommended. Consider using an alternative approach, for example, using a remote connection to a separate database instead. +ifndef::no-deprecated-test-resource[] ==== Run an integration test . Add a dependency on the artifacts providing the additional tools that are under the following Maven coordinates: @@ -720,6 +727,7 @@ public class TestResources { quarkus.datasource.db-kind=h2 quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:test ---- +endif::no-deprecated-test-resource[] [[datasource-reference]] == References @@ -912,9 +920,11 @@ a|* JDBC: `org.postgresql.Driver` |`reactive-pg-client` |`io.vertx.pgclient.spi.PgDriver` +ifndef::no-quarkus-reactive-db2-client[] |`db2` |`reactive-db2-client` |`io.vertx.db2client.spi.DB2Driver` +endif::no-quarkus-reactive-db2-client[] |=== [TIP] @@ -928,9 +938,11 @@ This automatic resolution is applicable in most cases so that driver configurati include::{generated-dir}/config/quarkus-reactive-datasource.adoc[opts=optional, leveloffset=+1] +ifndef::no-quarkus-reactive-db2-client[] ==== Reactive DB2 configuration include::{generated-dir}/config/quarkus-reactive-db2-client.adoc[opts=optional, leveloffset=+1] +endif::no-quarkus-reactive-db2-client[] ==== Reactive MariaDB/MySQL specific configuration diff --git a/docs/src/main/asciidoc/security-authentication-mechanisms.adoc b/docs/src/main/asciidoc/security-authentication-mechanisms.adoc index 30425666b7763..ee4997fd70865 100644 --- a/docs/src/main/asciidoc/security-authentication-mechanisms.adoc +++ b/docs/src/main/asciidoc/security-authentication-mechanisms.adoc @@ -35,15 +35,22 @@ The following table maps specific authentication requirements to a supported mec |Username and password |xref:security-basic-authentication.adoc[Basic], <> -|Bearer access token |xref:security-oidc-bearer-token-authentication.adoc[OIDC Bearer token authentication], xref:security-jwt.adoc[JWT], xref:security-oauth2.adoc[OAuth2] +|Bearer access token |xref:security-oidc-bearer-token-authentication.adoc[OIDC Bearer token authentication], xref:security-jwt.adoc[JWT] +ifndef::no-quarkus-elytron-security-oauth2[] +, xref:security-oauth2.adoc[OAuth2] +endif::no-quarkus-elytron-security-oauth2[] |Single sign-on (SSO) |xref:security-oidc-code-flow-authentication.adoc[OIDC Code Flow], <> |Client certificate |<> +ifndef::no-webauthn-authentication[] |WebAuthn |xref:security-webauthn.adoc[WebAuthn] +endif::no-webauthn-authentication[] +ifndef::no-quarkiverse[] |Kerberos ticket |link:https://quarkiverse.github.io/quarkiverse-docs/quarkus-kerberos/dev/index.html[Kerberos] +endif::no-quarkiverse[] |==== For more information, see the following <> table. @@ -96,7 +103,7 @@ quarkus.http.auth.form.error-page= # Define testing user quarkus.security.users.embedded.enabled=true quarkus.security.users.embedded.plain-text=true -quarkus.security.users.embedded.users.alice=alice +quarkus.security.users.embedded.users.alice=alice quarkus.security.users.embedded.roles.alice=user ---- @@ -312,17 +319,23 @@ For more information about customizing `SecurityIdentity`, see the xref:security Quarkus Security also supports the following authentication mechanisms through extensions: +ifndef::no-webauthn-authentication[] * <> +endif::no-webauthn-authentication[] * <> * <> +ifndef::no-quarkus-elytron-security-oauth2[] * <> +endif::no-quarkus-elytron-security-oauth2[] +ifndef::no-webauthn-authentication[] [[webauthn-authentication]] === WebAuthn authentication https://webauthn.guide/[WebAuthn] is an authentication mechanism that replaces passwords. When you write a service for registering new users, or logging them in, instead of asking for a password, you can use WebAuthn, which replaces the password. For more information, see the xref:security-webauthn.adoc[Secure a Quarkus application by using the WebAuthn authentication mechanism] guide. +endif::no-webauthn-authentication[] [[openid-connect-authentication]] === OpenID Connect authentication @@ -357,7 +370,9 @@ For more information about OIDC authentication and authorization methods that yo |Multiple tenants that can support the Bearer token authentication or Authorization Code Flow mechanisms|xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect (OIDC) multi-tenancy] |Securing Quarkus with commonly used OpenID Connect providers|xref:security-openid-connect-providers.adoc[Configuring well-known OpenID Connect providers] |Using Keycloak to centralize authorization |xref:security-keycloak-authorization.adoc[Using OpenID Connect (OIDC) and Keycloak to centralize authorization] +ifndef::no-quarkus-keycloak-admin-client[] |Configuring Keycloak programmatically |xref:security-keycloak-admin-client.adoc[Using the Keycloak admin client] +endif::no-quarkus-keycloak-admin-client[] |==== [NOTE] @@ -386,12 +401,15 @@ For example, it can be a public endpoint or be protected with mTLS. In this scenario, you do not need to protect your Quarkus endpoint by using the Quarkus OpenID Connect adapter. ==== +ifndef::no-quarkus-oidc-token-propagation[] The `quarkus-resteasy-client-oidc-token-propagation` extension requires the `quarkus-oidc` extension. It provides Jakarta REST `TokenCredentialRequestFilter`, which sets the OpenID Connect Bearer token or Authorization Code Flow access token as the `Bearer` scheme value of the HTTP `Authorization` header. This filter can be registered with MicroProfile REST client implementations injected into the current Quarkus endpoint, which must be protected by using the Quarkus OIDC adapter. This filter can propagate the access token to the downstream services. For more information, see the xref:security-openid-connect-client.adoc[OpenID Connect client and token propagation quickstart] and xref:security-openid-connect-client-reference.adoc[OpenID Connect (OIDC) and OAuth2 client and filters reference] guides. +endif::no-quarkus-oidc-token-propagation[] + [[smallrye-jwt-authentication]] === SmallRye JWT authentication @@ -404,6 +422,7 @@ It represents them as `org.eclipse.microprofile.jwt.JsonWebToken`. For more information, see the xref:security-jwt.adoc[Using JWT RBAC] guide. +ifndef::no-quarkus-elytron-security-oauth2[] [[oauth2-authentication]] === OAuth2 authentication @@ -411,6 +430,7 @@ For more information, see the xref:security-jwt.adoc[Using JWT RBAC] guide. `quarkus-elytron-security-oauth2` is based on `Elytron` and is primarily intended for introspecting opaque tokens remotely. For more information, see the Quarkus xref:security-oauth2.adoc[Using OAuth2] guide. +endif::no-quarkus-elytron-security-oauth2[] [[oidc-jwt-oauth2-comparison]] == Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms @@ -425,13 +445,20 @@ In both cases, `quarkus-oidc` requires a connection to the specified OpenID Conn * If the user authentication requires Authorization Code flow, or you need to support multiple tenants, use `quarkus-oidc`. `quarkus-oidc` can also request user information by using both Authorization Code Flow and Bearer access tokens. -* If your bearer tokens must be verified, use `quarkus-oidc`, `quarkus-smallrye-jwt`, or `quarkus-elytron-security-oauth2`. +ifndef::no-quarkus-elytron-security-oauth2[] +* If your bearer tokens must be verified, use `quarkus-oidc`, `quarkus-elytron-security-oauth2`, or `quarkus-smallrye-jwt`. +endif::no-quarkus-elytron-security-oauth2[] +ifdef::no-quarkus-elytron-security-oauth2[] +* If your bearer tokens must be verified, use `quarkus-oidc` or `quarkus-smallrye-jwt`. +endif::no-quarkus-elytron-security-oauth2[] * If your bearer tokens are in a JSON web token (JWT) format, you can use any extensions in the preceding list. Both `quarkus-oidc` and `quarkus-smallrye-jwt` support refreshing the `JsonWebKey` (JWK) set when the OpenID Connect provider rotates the keys. Therefore, if remote token introspection must be avoided or is unsupported by the providers, use `quarkus-oidc` or `quarkus-smallrye-jwt` to verify JWT tokens. -* To introspect the JWT tokens remotely, you can use either `quarkus-oidc` or `quarkus-elytron-security-oauth2` because they support verifying the opaque or binary tokens by using remote introspection. +* To introspect the JWT tokens remotely, you can use `quarkus-oidc` +ifndef::no-quarkus-elytron-security-oauth2[or `quarkus-elytron-security-oauth2`] +for verifying the opaque or binary tokens by using remote introspection. `quarkus-smallrye-jwt` does not support the remote introspection of both opaque or JWT tokens but instead relies on the locally available keys that are usually retrieved from the OpenID Connect provider. * `quarkus-oidc` and `quarkus-smallrye-jwt` support the JWT and opaque token injection into the endpoint code. @@ -442,9 +469,10 @@ All extensions can have the tokens injected as `Principal`. `quarkus-oidc` uses only the JWK-formatted keys that are part of a JWK set, whereas `quarkus-smallrye-jwt` supports PEM keys. * `quarkus-smallrye-jwt` handles locally signed, inner-signed-and-encrypted, and encrypted tokens. -In contrast, although `quarkus-oidc` and `quarkus-elytron-security-oauth2` can also verify such tokens, they treat them as opaque tokens and verify them through remote introspection. +ifndef::no-quarkus-elytron-security-oauth2[In contrast, although `quarkus-oidc` and `quarkus-elytron-security-oauth2` can also verify such tokens, they treat them as opaque tokens and verify them through remote introspection.] +ifdef::no-quarkus-elytron-security-oauth2[In contrast, although `quarkus-oidc` can also verify such tokens, it treats them as opaque tokens and verifies them through remote introspection.] -* If you need a lightweight library for the remote introspection of opaque or JWT tokens, use `quarkus-elytron-security-oauth2`. +ifndef::no-quarkus-elytron-security-oauth2[* If you need a lightweight library for the remote introspection of opaque or JWT tokens, use `quarkus-elytron-security-oauth2`.] [NOTE] ==== @@ -459,26 +487,80 @@ Nonetheless, the providers effectively delegate most of the token-associated sta [[table]] .Token authentication mechanism comparison |=== -^|Feature required 3+^| Authentication mechanism - -^| ^s|`quarkus-oidc` ^s|`quarkus-smallrye-jwt` ^s| `quarkus-elytron-security-oauth2` - -s|Bearer JWT verification ^|Local verification or introspection ^|Local verification ^|Introspection - -s|Bearer opaque token verification ^|Introspection ^|No ^|Introspection -s|Refreshing `JsonWebKey` set to verify JWT tokens ^|Yes ^|Yes ^|No -s|Represent token as `Principal` ^|Yes ^|Yes ^|Yes -s|Inject JWT as MP JWT ^|Yes ^|Yes ^|No - -s|Authorization code flow ^| Yes ^|No ^|No -s|Multi-tenancy ^| Yes ^|No ^|No -s|User information support ^| Yes ^|No ^|No -s|PEM key format support ^|No ^|Yes ^|No - -s|SecretKey support ^|No ^|In JSON Web Key (JWK) format ^|No -s|Inner-signed and encrypted or encrypted tokens ^|Introspection ^|Local verification ^|Introspection -s|Custom token verification ^|No ^|With injected JWT parser ^|No -s|JWT as a cookie support ^|No ^|Yes ^|Yes +// Display four columns +ifndef::no-quarkus-elytron-security-oauth2[ ^|Feature required 3+^| Authentication mechanism] +// Display three columns and hide the quarkus-elytron-security-oauth2 column. +ifdef::no-quarkus-elytron-security-oauth2[ ^|Feature required 2+^| Authentication mechanism] + +^| +^s|`quarkus-oidc` +^s|`quarkus-smallrye-jwt` +ifndef::no-quarkus-elytron-security-oauth2[ ^s|`quarkus-elytron-security-oauth2`] + +s|Bearer JWT verification +^|Local verification or introspection +^|Local verification +ifndef::no-quarkus-elytron-security-oauth2[ ^|Introspection] + +s|Bearer opaque token verification +^|Introspection +^|No +ifndef::no-quarkus-elytron-security-oauth2[ ^|Introspection] + +s|Refreshing `JsonWebKey` set to verify JWT tokens +^|Yes +^|Yes +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|Represent token as `Principal` +^|Yes +^|Yes +ifndef::no-quarkus-elytron-security-oauth2[ ^|Yes] + +s|Inject JWT as MP JWT +^|Yes +^|Yes +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|Authorization code flow +^| Yes +^|No +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|Multi-tenancy +^| Yes +^|No +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|User information support +^| Yes +^|No +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|PEM key format support +^|No +^|Yes +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|SecretKey support +^|No +^|In JSON Web Key (JWK) format +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|Inner-signed and encrypted or encrypted tokens +^|Introspection +^|Local verification +ifndef::no-quarkus-elytron-security-oauth2[ ^|Introspection] + +s|Custom token verification +^|No +^|With injected JWT parser +ifndef::no-quarkus-elytron-security-oauth2[ ^|No] + +s|JWT as a cookie support +^|No +^|Yes +ifndef::no-quarkus-elytron-security-oauth2[ ^|Yes] |=== [[combining-authentication-mechanisms]] @@ -560,13 +642,29 @@ public class HelloResource { |=== ^|Authentication mechanism^| Annotation -s|Basic authentication mechanism ^|`io.quarkus.vertx.http.runtime.security.annotation.BasicAuthentication` -s|Form-based authentication mechanism ^|`io.quarkus.vertx.http.runtime.security.annotation.FormAuthentication` -s|Mutual TLS authentication mechanism ^|`io.quarkus.vertx.http.runtime.security.annotation.MTLSAuthentication` -s|WebAuthn authentication mechanism ^|`io.quarkus.security.webauthn.WebAuthn` -s|Bearer token authentication mechanism ^|`io.quarkus.oidc.BearerTokenAuthentication` -s|OIDC authorization code flow mechanism ^|`io.quarkus.oidc.AuthorizationCodeFlow` -s|SmallRye JWT authentication mechanism ^|`io.quarkus.smallrye.jwt.runtime.auth.BearerTokenAuthentication` +s|Basic authentication mechanism +^|`io.quarkus.vertx.http.runtime.security.annotation.BasicAuthentication` + +s|Form-based authentication mechanism +^|`io.quarkus.vertx.http.runtime.security.annotation.FormAuthentication` + +s|Mutual TLS authentication mechanism +^|`io.quarkus.vertx.http.runtime.security.annotation.MTLSAuthentication` + +ifndef::no-webauthn-authentication[] +s|WebAuthn authentication mechanism +^|`io.quarkus.security.webauthn.WebAuthn` +endif::no-webauthn-authentication[] + +s|Bearer token authentication mechanism +^|`io.quarkus.oidc.BearerTokenAuthentication` + +s|OIDC authorization code flow mechanism +^|`io.quarkus.oidc.AuthorizationCodeFlow` + +s|SmallRye JWT authentication mechanism +^|`io.quarkus.smallrye.jwt.runtime.auth.BearerTokenAuthentication` + |=== TIP: Quarkus automatically secures endpoints annotated with the authentication mechanism annotation. When no standard security annotation is present on the REST endpoint and resource, the `io.quarkus.security.Authenticated` annotation is added for you. diff --git a/docs/src/main/asciidoc/security-basic-authentication-howto.adoc b/docs/src/main/asciidoc/security-basic-authentication-howto.adoc index 015127dbfb430..e346a2f31d64e 100644 --- a/docs/src/main/asciidoc/security-basic-authentication-howto.adoc +++ b/docs/src/main/asciidoc/security-basic-authentication-howto.adoc @@ -18,7 +18,12 @@ Enable xref:security-basic-authentication.adoc[Basic authentication] for your Qu * You have installed at least one extension that provides an `IdentityProvider` based on username and password. For example: -** xref:security-jpa.adoc[Quarkus Security Jakarta Persistence extensions (`security-jpa` or `security-jpa-reactive`)] +ifndef::no-quarkus-security-jpa-reactive[] +** xref:security-jpa.adoc[Quarkus Security Jakarta Persistence extensions (`quarkus-security-jpa` or `quarkus-security-jpa-reactive`)] +endif::no-quarkus-security-jpa-reactive[] +ifdef::no-quarkus-security-jpa-reactive[] +** xref:security-jpa.adoc[Quarkus Security Jakarta Persistence extension (`quarkus-security-jpa`)] +endif::no-quarkus-security-jpa-reactive[] ** xref:security-properties.adoc[Elytron security properties file extension `(quarkus-elytron-security-properties-file)`] ** xref:security-jdbc.adoc[Elytron security JDBC extension `(quarkus-elytron-security-jdbc)`] diff --git a/docs/src/main/asciidoc/security-getting-started-tutorial.adoc b/docs/src/main/asciidoc/security-getting-started-tutorial.adoc index 29311a068cf7d..5dcab363d539b 100644 --- a/docs/src/main/asciidoc/security-getting-started-tutorial.adoc +++ b/docs/src/main/asciidoc/security-getting-started-tutorial.adoc @@ -54,12 +54,20 @@ You can find the solution in the `security-jpa-quickstart` link:{quickstarts-tre == Create and verify the Maven project -For Quarkus Security to be able to map your security source to Jakarta Persistence entities, ensure that the Maven project in this tutorial includes the `security-jpa` or `security-jpa-reactive` extension. +ifndef::no-quarkus-security-jpa-reactive[] +For Quarkus Security to be able to map your security source to Jakarta Persistence entities, ensure that the Maven project in this tutorial includes the `quarkus-security-jpa` or `quarkus-security-jpa-reactive` extension. +endif::no-quarkus-security-jpa-reactive[] +ifdef::no-quarkus-security-jpa-reactive[] +For Quarkus Security to be able to map your security source to Jakarta Persistence entities, ensure that the Maven project in this tutorial includes the `quarkus-security-jpa` extension. +endif::no-quarkus-security-jpa-reactive[] [NOTE] ==== -xref:hibernate-orm-panache.adoc[Hibernate ORM with Panache] is used to store your user identities, but you can also use xref:hibernate-orm.adoc[Hibernate ORM] with the `security-jpa` extension. -Both xref:hibernate-reactive.adoc[Hibernate Reactive] and xref:hibernate-reactive-panache.adoc[Hibernate Reactive with Panache] can be used with the `security-jpa-reactive` extension. +xref:hibernate-orm-panache.adoc[Hibernate ORM with Panache] is used to store your user identities, but you can also use xref:hibernate-orm.adoc[Hibernate ORM] with the `quarkus-security-jpa` extension. + +ifndef::no-quarkus-security-jpa-reactive[] +Both xref:hibernate-reactive.adoc[Hibernate Reactive] and xref:hibernate-reactive-panache.adoc[Hibernate Reactive with Panache] can be used with the `quarkus-security-jpa-reactive` extension. +endif::no-quarkus-security-jpa-reactive[] You must also add your preferred database connector library. The instructions in this example tutorial use a PostgreSQL database for the identity store. @@ -86,18 +94,20 @@ include::{includes}/devtools/create-app.adoc[] :add-extension-extensions: security-jpa include::{includes}/devtools/extension-add.adoc[] ==== +ifndef::no-quarkus-security-jpa-reactive[] ** To add the Security Jakarta Persistence extension to an existing Maven project with Hibernate Reactive, run the following command from your project base directory: + ==== :add-extension-extensions: security-jpa-reactive include::{includes}/devtools/extension-add.adoc[] ==== +endif::no-quarkus-security-jpa-reactive[] === Verify the quarkus-security-jpa dependency -After you have run either of the preceding commands to create the Maven project, verify that the `security-jpa` dependency was added to your project build XML file. +After you have run either of the preceding commands to create the Maven project, verify that the `quarkus-security-jpa` dependency was added to your project build XML file. -* To verify the `security-jpa` extension, check for the following configuration: +* To verify the `quarkus-security-jpa` extension, check for the following configuration: + ==== [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] @@ -115,7 +125,8 @@ After you have run either of the preceding commands to create the Maven project, implementation("io.quarkus:quarkus-security-jpa") ---- ==== -* To verify the `security-jpa-reactive` extension, check for the following configuration: +ifndef::no-quarkus-security-jpa-reactive[] +* To verify the `quarkus-security-jpa-reactive` extension, check for the following configuration: + ==== [source,xml,role="primary asciidoc-tabs-target-sync-cli asciidoc-tabs-target-sync-maven"] @@ -133,6 +144,7 @@ implementation("io.quarkus:quarkus-security-jpa") implementation("io.quarkus:quarkus-security-jpa-reactive") ---- ==== +endif::no-quarkus-security-jpa-reactive[] == Write the application @@ -266,7 +278,7 @@ public class User extends PanacheEntity { ---- -The `security-jpa` extension only initializes if a single entity is annotated with `@UserDefinition`. +The `quarkus-security-jpa` extension only initializes if a single entity is annotated with `@UserDefinition`. <1> The `@UserDefinition` annotation must be present on a single entity, either a regular Hibernate ORM entity or a Hibernate ORM with Panache entity. <2> Indicates the field used for the username. @@ -280,12 +292,13 @@ You can configure it to use plain text or custom passwords. ==== Don’t forget to set up the Panache and PostgreSQL JDBC driver, please see xref:hibernate-orm-panache.adoc#setting-up-and-configuring-hibernate-orm-with-panache[Setting up and configuring Hibernate ORM with Panache] for more information. ==== - +ifndef::no-quarkus-security-jpa-reactive[] [NOTE] ==== Hibernate Reactive Panache uses `io.quarkus.hibernate.reactive.panache.PanacheEntity` instead of `io.quarkus.hibernate.orm.panache.PanacheEntity`. For more information, see link:{quickstarts-tree-url}/security-jpa-reactive-quickstart/src/main/java/org/acme/elytron/security/jpa/reactive/User.java[User file]. ==== +endif::no-quarkus-security-jpa-reactive[] == Configure the application @@ -299,7 +312,7 @@ When secure access is required, and no other authentication mechanisms are enabl Therefore, in this tutorial, you do not need to set the property `quarkus.http.auth.basic` to `true`. ==== + -. Configure at least one data source in the `application.properties` file so the `security-jpa` extension can access your database. +. Configure at least one data source in the `application.properties` file so the `quarkus-security-jpa` extension can access your database. For example: + ==== @@ -318,9 +331,10 @@ quarkus.hibernate-orm.database.generation=drop-and-create + . To initialize the database with users and roles, implement the `Startup` class, as outlined in the following code snippet: +ifndef::no-quarkus-security-jpa-reactive[] [NOTE] ==== -* The URLs of Reactive datasources that are used by the `security-jpa-reactive` extension are set with the `quarkus.datasource.reactive.url` +* The URLs of Reactive datasources that are used by the `quarkus-security-jpa-reactive` extension are set with the `quarkus.datasource.reactive.url` configuration property and not the `quarkus.datasource.jdbc.url` configuration property typically used by JDBC datasources. + [source,properties] @@ -333,6 +347,7 @@ link:https://hibernate.org/orm/[Hibernate ORM] automatically creates the databas This approach is suitable for development but is not recommended for production. Therefore, adjustments are needed in a production environment. ==== +endif::no-quarkus-security-jpa-reactive[] [source,java] ---- @@ -362,7 +377,7 @@ The preceding example demonstrates how the application can be protected and iden [IMPORTANT] ==== In a production environment, do not store plain text passwords. -As a result, the `security-jpa` defaults to using bcrypt-hashed passwords. +As a result, the `quarkus-security-jpa` defaults to using bcrypt-hashed passwords. ==== == Test your application by using Dev Services for PostgreSQL diff --git a/docs/src/main/asciidoc/security-jpa.adoc b/docs/src/main/asciidoc/security-jpa.adoc index d114c46cf9666..0eefd1783de9e 100644 --- a/docs/src/main/asciidoc/security-jpa.adoc +++ b/docs/src/main/asciidoc/security-jpa.adoc @@ -78,12 +78,12 @@ public class User extends PanacheEntity { ---- -The `security-jpa` extension initializes only if a single entity is annotated with `@UserDefinition`. +The `quarkus-security-jpa` extension initializes only if a single entity is annotated with `@UserDefinition`. <1> The `@UserDefinition` annotation must be present on a single entity, either a regular Hibernate ORM entity or a Hibernate ORM with Panache entity. <2> Indicates the field used for the username. <3> Indicates the field used for the password. -By default, `security-jpa` uses bcrypt-hashed passwords, or you can configure plain text or custom passwords instead. +By default, `quarkus-security-jpa` uses bcrypt-hashed passwords, or you can configure plain text or custom passwords instead. <4> This indicates the comma-separated list of roles added to the target principal representation attributes. <5> This method lets you add users while hashing passwords with the proper `bcrypt` hash. diff --git a/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc index c44e4346d19eb..6e1ffbb1d991f 100644 --- a/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc +++ b/docs/src/main/asciidoc/security-oidc-auth0-tutorial.adoc @@ -887,6 +887,7 @@ Open a browser, access http://localhost:8080/hello and get the name displayed in To confirm the permission is correctly enforced, change it to `echo.name`: `@PermissionsAllowed("echo.name")`. Clear the browser cache, access http://localhost:8080/hello again and you will get `403` reported by `ApiEchoService`. Now revert it back to `@PermissionsAllowed("echo:name")`. +ifndef::no-deprecated-test-resource[] == Integration testing You have already used OIDC DevUI SPA to login to Auth0 and test the Quarkus endpoint with the access token, updating the endpoint code along the way. @@ -1035,6 +1036,7 @@ image::auth0-test-success.png[Auth0 test success] By the way, if you like, you can run the tests in Continuous mode directly from DevUI: image::auth0-continuous-testing.png[Auth0 Continuous testing] +endif::no-deprecated-test-resource[] [[production-mode]] == Production mode diff --git a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication-tutorial.adoc index 6b2f9b06a891a..67717da4065b1 100644 --- a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication-tutorial.adoc +++ b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication-tutorial.adoc @@ -228,13 +228,14 @@ docker run --name keycloak -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=ad For more information, see the Keycloak documentation about link:https://www.keycloak.org/docs/latest/server_admin/index.html#configuring-realms[creating and configuring a new realm]. - +ifndef::no-quarkus-keycloak-admin-client[] [NOTE] ==== If you want to use the Keycloak Admin Client to configure your server from your application, you need to include either the `quarkus-keycloak-admin-rest-client` or the `quarkus-keycloak-admin-resteasy-client` (if the application uses `quarkus-rest-client`) extension. For more information, see the xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] guide. - ==== +endif::no-quarkus-keycloak-admin-client[] + [[keycloak-dev-mode]] @@ -367,4 +368,6 @@ For information about writing integration tests that depend on `Dev Services for * xref:security-jwt-build.adoc[Sign and encrypt JWT tokens with SmallRye JWT Build] * xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview.adoc[Quarkus Security overview] +ifndef::no-quarkus-keycloak-admin-client[] * xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] +endif::no-quarkus-keycloak-admin-client[] diff --git a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc index b1c4bd9180b8f..12cc7b961b0dc 100644 --- a/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc +++ b/docs/src/main/asciidoc/security-oidc-bearer-token-authentication.adoc @@ -855,6 +855,7 @@ public class NativeBearerTokenAuthenticationIT extends BearerTokenAuthentication For more information about initializing and configuring Dev Services for Keycloak, see the xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] guide. +ifndef::no-deprecated-test-resource[] [[integration-testing-keycloak]] ==== `KeycloakTestResourceLifecycleManager` @@ -957,6 +958,7 @@ By default: By default, `KeycloakTestResourceLifecycleManager` uses HTTPS to initialize a Keycloak instance, and this can be disabled by using `keycloak.use.https=false`. The default realm name is `quarkus`, and the client id is `quarkus-service-app`. If you want to customize these values, set the `keycloak.realm` and `keycloak.service.client` system properties. +endif::no-deprecated-test-resource[] [[integration-testing-public-key]] ==== Local public key @@ -1356,5 +1358,7 @@ For more information, see xref:security-oidc-code-flow-authentication#oidc-reque * xref:security-authentication-mechanisms.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms] * xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview.adoc[Quarkus Security overview] +ifndef::no-quarkus-keycloak-admin-client[] * xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] +endif::no-quarkus-keycloak-admin-client[] * xref:security-openid-connect-multitenancy.adoc[Using OpenID Connect Multi-Tenancy] diff --git a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc index 4ccd40e661a68..2a8c6219970bf 100644 --- a/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc +++ b/docs/src/main/asciidoc/security-oidc-code-flow-authentication-tutorial.adoc @@ -278,7 +278,9 @@ After you have completed this tutorial, explore xref:security-oidc-bearer-token- * 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.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms] +ifndef::no-quarkus-keycloak-admin-client[] * xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] +endif::no-quarkus-keycloak-admin-client[] * https://www.keycloak.org/documentation.html[Keycloak Documentation] * xref:security-oidc-auth0-tutorial.adoc[Protect Quarkus web application by using Auth0 OpenID Connect provider] * https://openid.net/connect/[OpenID Connect] diff --git a/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc b/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc index e35ca4f0aade5..cc9502024c45d 100644 --- a/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc +++ b/docs/src/main/asciidoc/security-oidc-code-flow-authentication.adoc @@ -515,7 +515,7 @@ Set the `quarkus.oidc.authentication.user-info-required=true` property to reques A request is sent to the OIDC provider `UserInfo` endpoint by using the access token returned with the authorization code grant response, and an `io.quarkus.oidc.UserInfo` (a simple `jakarta.json.JsonObject` wrapper) object is created. `io.quarkus.oidc.UserInfo` can be injected or accessed as a SecurityIdentity `userinfo` attribute. -`quarkus.oidc.authentication.user-info-required` is automatically enabled if one of these conditions is met: +`quarkus.oidc.authentication.user-info-required` is automatically enabled if one of these conditions is met: - if `quarkus.oidc.roles.source` is set to `userinfo` or `quarkus.oidc.token.verify-access-token-with-user-info` is set to `true` or `quarkus.oidc.authentication.id-token-required` is set to `false`, the current OIDC tenant must support a UserInfo endpoint in these cases. @@ -661,8 +661,11 @@ OIDC `CodeAuthenticationMechanism` uses the default `io.quarkus.oidc.TokenStateM It makes Quarkus OIDC endpoints completely stateless and it is recommended to follow this strategy to achieve the best scalability results. -See the <> and <> sections of this guide for alternative approaches to storing tokens. -For example, storing tokens in the database or other server-side storage, if you prefer and have good reasons for storing the token state on the server. +ifndef::no-quarkus-oidc-db-token-state-manager[] +Refer to the <> section of this guide for information on storing tokens in the database or other server-side storage solutions. This approach is suitable if you prefer and have compelling reasons to store the token state on the server. +endif::no-quarkus-oidc-db-token-state-manager[] + +See the <> section for alternative methods of token storage. This is ideal for those seeking customized solutions for token state management, especially when standard server-side storage does not meet your specific requirements. You can configure the default `TokenStateManager` to avoid saving an access token in the session cookie and to only keep ID and refresh tokens or a single ID token only. @@ -688,8 +691,10 @@ In such cases, use the `quarkus.oidc.token-state-manager.strategy` property to c If your chosen session cookie strategy combines tokens and generates a large session cookie value that is greater than 4KB, some browsers might not be able to handle such cookie sizes. This can occur when the ID, access, and refresh tokens are JWT tokens and the selected strategy is `keep-all-tokens` or with ID and refresh tokens when the strategy is `id-refresh-token`. To work around this issue, you can set `quarkus.oidc.token-state-manager.split-tokens=true` to create a unique session token for each token. +ifndef::no-quarkus-oidc-db-token-state-manager[] An alternative solution is to have the tokens saved in the database. For more information, see <>. +endif::no-quarkus-oidc-db-token-state-manager[] The default `TokenStateManager` encrypts the tokens before storing them in the session cookie. The following example shows how you configure it to split the tokens and encrypt them: @@ -781,6 +786,7 @@ public class CustomTokenStateManager implements TokenStateManager { For information about the default `TokenStateManager` storing tokens in an encrypted session cookie, see <>. +ifndef::no-quarkus-oidc-db-token-state-manager[] For information about the custom Quarkus `TokenStateManager` implementation storing tokens in a database, see <>. [[db-token-state-manager]] @@ -882,6 +888,7 @@ public class OidcDbTokenStateManagerEntity { <1> The Hibernate ORM extension will only create this table for you when the database schema is generated. For more information, refer to the xref:hibernate-orm.adoc[Hibernate ORM] guide. <2> You can choose a column length depending on the length of your tokens. +endif::no-quarkus-oidc-db-token-state-manager[] === Logout and expiration @@ -1409,6 +1416,7 @@ Future callQuarkusService() async { If you plan to consume this application from a single-page application running on a different domain, you need to configure cross-origin resource sharing (CORS). For more information, see the xref:security-cors.adoc#cors-filter[CORS filter] section of the "Cross-origin resource sharing" guide. +ifndef::no-quarkiverse[] === Calling Cloud provider services ==== Google Cloud @@ -1444,6 +1452,7 @@ quarkus.oidc.client-id={GOOGLE_CLIENT_ID} quarkus.oidc.credentials.secret={GOOGLE_CLIENT_SECRET} quarkus.oidc.token.issuer=https://accounts.google.com ---- +endif::no-quarkiverse[] === Running Quarkus application behind a reverse proxy @@ -1564,6 +1573,7 @@ testImplementation("net.sourceforge.htmlunit:htmlunit") testImplementation("io.quarkus:quarkus-junit5") ---- +ifndef::no-deprecated-test-resource[] [[integration-testing-wiremock]] === Wiremock @@ -1650,6 +1660,7 @@ The user `admin` has the `user` and `admin` roles by default - it can be customi Additionally, `OidcWiremockTestResource` sets the token issuer and audience to `https://service.example.com`, which can be customized with `quarkus.test.oidc.token.issuer` and `quarkus.test.oidc.token.audience` system properties. `OidcWiremockTestResource` can be used to emulate all OIDC providers. +endif::no-deprecated-test-resource[] [[integration-testing-keycloak-devservices]] === Dev Services for Keycloak @@ -1686,6 +1697,7 @@ public class CodeFlowAuthorizationTest { } ---- +ifndef::no-deprecated-test-resource[] [[integration-testing-keycloak]] === Using KeycloakTestResourceLifecycleManager @@ -1750,6 +1762,7 @@ The user `admin` has the `user` and `admin` roles by default - it can be customi By default, `KeycloakTestResourceLifecycleManager` uses HTTPS to initialize a Keycloak instance that can be disabled by specifying `keycloak.use.https=false`. The default realm name is `quarkus` and client id is `quarkus-web-app` - set `keycloak.realm` and `keycloak.web-app.client` system properties to customize the values if needed. +endif::no-deprecated-test-resource[] [[integration-testing-security-annotation]] === TestSecurity annotation @@ -1795,4 +1808,3 @@ From the `quarkus dev` console, type `j` to change the application global log le * https://www.keycloak.org/documentation.html[Keycloak documentation] * https://openid.net/connect/[OpenID Connect] * https://tools.ietf.org/html/rfc7519[JSON Web Token] - diff --git a/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc b/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc index 438a9f72a3ec4..e76df52eb6375 100644 --- a/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc +++ b/docs/src/main/asciidoc/security-oidc-configuration-properties-reference.adoc @@ -19,14 +19,8 @@ include::{generated-dir}/config/quarkus-oidc.adoc[opts=optional, leveloffset=+1] * xref:security-oidc-bearer-token-authentication.adoc[OIDC Bearer token authentication] * xref:security-oidc-bearer-token-authentication-tutorial.adoc[Protect a service application by using OpenID Connect (OIDC) Bearer token authentication] -// * 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.adoc#oidc-jwt-oauth2-comparison[Choosing between OpenID Connect, SmallRye JWT, and OAuth2 authentication mechanisms] * xref:security-authentication-mechanisms.adoc#combining-authentication-mechanisms[Combining authentication mechanisms] * xref:security-overview.adoc[Quarkus Security] -// * xref:security-keycloak-admin-client.adoc[Quarkus Keycloak Admin Client] -// TASK - Select some references and eliminate the rest. diff --git a/docs/src/main/asciidoc/security-openid-connect-client-reference.adoc b/docs/src/main/asciidoc/security-openid-connect-client-reference.adoc index db214a15dbe15..6bceac124346a 100644 --- a/docs/src/main/asciidoc/security-openid-connect-client-reference.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-client-reference.adoc @@ -15,7 +15,11 @@ You can use Quarkus extensions for OpenID Connect and OAuth 2.0 access token man This includes the following: - Using `quarkus-oidc-client`, `quarkus-rest-client-oidc-filter` and `quarkus-resteasy-client-oidc-filter` extensions to acquire and refresh access tokens from OpenID Connect and OAuth 2.0 compliant Authorization Servers such as link:https://www.keycloak.org[Keycloak]. + +ifndef::no-quarkus-oidc-token-propagation[] + - Using `quarkus-rest-client-oidc-token-propagation` and `quarkus-resteasy-client-oidc-token-propagation` extensions to propagate the current `Bearer` or `Authorization Code Flow` access tokens. +endif::no-quarkus-oidc-token-propagation[] The access tokens managed by these extensions can be used as HTTP Authorization Bearer tokens to access the remote services. @@ -1097,6 +1101,7 @@ public class OidcRequestCustomizer implements OidcRequestFilter { } ---- +ifndef::no-quarkus-oidc-token-propagation-reactive[] [[token-propagation-reactive]] == Token Propagation Reactive @@ -1172,7 +1177,9 @@ quarkus.oidc-token-propagation.exchange-token=true ---- `AccessTokenRequestReactiveFilter` uses a default `OidcClient` by default. A named `OidcClient` can be selected with a `quarkus.oidc-token-propagation-reactive.client-name` configuration property or with the `io.quarkus.oidc.token.propagation.AccessToken#exchangeTokenClient` annotation attribute. +endif::no-quarkus-oidc-token-propagation-reactive[] +ifndef::no-quarkus-oidc-token-propagation[] [[token-propagation]] == Token Propagation @@ -1187,6 +1194,7 @@ However, the direct end-to-end Bearer token propagation should be avoided. For e Additionally, a complex application might need to exchange or update the tokens before propagating them. For example, the access context might be different when `Service A` is accessing `Service B`. In this case, `Service A` might be granted a narrow or completely different set of scopes to access `Service B`. The following sections show how `AccessTokenRequestFilter` and `JsonWebTokenRequestFilter` can help. +endif::no-quarkus-oidc-token-propagation[] === RestClient AccessTokenRequestFilter @@ -1328,6 +1336,7 @@ As mentioned, use `AccessTokenRequestFilter` if you work with Keycloak or an Ope You can generate the tokens as described in xref:security-oidc-bearer-token-authentication.adoc#integration-testing[OpenID Connect Bearer Token Integration testing] section. Prepare the REST test endpoints. You can have the test front-end endpoint, which uses the injected MP REST client with a registered token propagation filter, call the downstream endpoint. For example, see the `integration-tests/resteasy-client-oidc-token-propagation` in the `main` Quarkus repository. +ifndef::no-quarkus-oidc-token-propagation[] [[reactive-token-propagation]] == Token Propagation Reactive @@ -1345,8 +1354,10 @@ The `quarkus-rest-client-resteasy-client-oidc-token-propagation` extension provi The `quarkus-rest-client-resteasy-client-oidc-token-propagation` extension (as opposed to the non-reactive `quarkus-resteasy-client-oidc-token-propagation` extension) does not currently support the exchanging or resigning of the tokens before the propagation. However, these features might be added in the future. +endif::no-quarkus-oidc-token-propagation[] -[[oidc-client-graphql-client]] +ifndef::no-quarkus-oidc-client-graphql[] +[[quarkus-oidc-client-graphql]] == GraphQL client integration The `quarkus-oidc-client-graphql` extension provides a way to integrate an OIDC client into xref:smallrye-graphql-client.adoc[GraphQL clients] paralleling the approach used with REST clients. @@ -1401,6 +1412,7 @@ Uni tokenUni = oidcClients.getClient("OIDC_CLIENT_NAME") builder.dynamicHeader("Authorization", tokenUni); VertxDynamicGraphQLClient client = builder.build(); ---- +endif::no-quarkus-oidc-client-graphql[] [[configuration-reference]] == Configuration reference @@ -1409,9 +1421,11 @@ VertxDynamicGraphQLClient client = builder.build(); include::{generated-dir}/config/quarkus-oidc-client.adoc[opts=optional, leveloffset=+1] +ifndef::no-quarkus-oidc-token-propagation-reactive[] === OIDC token propagation include::{generated-dir}/config/quarkus-oidc-token-propagation-reactive.adoc[opts=optional, leveloffset=+1] +endif::no-quarkus-oidc-token-propagation-reactive[] == References diff --git a/docs/src/main/asciidoc/security-openid-connect-client.adoc b/docs/src/main/asciidoc/security-openid-connect-client.adoc index 6594912214038..9876031aee273 100644 --- a/docs/src/main/asciidoc/security-openid-connect-client.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-client.adoc @@ -68,6 +68,7 @@ The solution is in the `security-openid-connect-client-quickstart` link:{quickst First, you need a new project. Create a new project with the following command: +ifndef::no-quarkus-oidc-token-propagation[] :create-app-artifact-id: security-openid-connect-client-quickstart :create-app-extensions: oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest include::{includes}/devtools/create-app.adoc[] @@ -78,6 +79,20 @@ If you already have your Quarkus project configured, you can add these extension :add-extension-extensions: oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest include::{includes}/devtools/extension-add.adoc[] +endif::no-quarkus-oidc-token-propagation[] + +ifdef::no-quarkus-oidc-token-propagation[] +:create-app-artifact-id: security-openid-connect-client-quickstart +:create-app-extensions: oidc,rest-client-oidc-filter,rest +include::{includes}/devtools/create-app.adoc[] + +It generates a Maven project, importing the `oidc`, `rest-client-oidc-filter`, and `rest` extensions. + +If you already have your Quarkus project configured, you can add these extensions to your project by running the following command in your project base directory: + +:add-extension-extensions: oidc,rest-client-oidc-filter,rest +include::{includes}/devtools/extension-add.adoc[] +endif::no-quarkus-oidc-token-propagation[] It adds the following extensions to your build file: @@ -92,21 +107,31 @@ It adds the following extensions to your build file: io.quarkus quarkus-rest-client-oidc-filter +ifndef::no-quarkus-oidc-token-propagation[] io.quarkus quarkus-rest-client-oidc-token-propagation +endif::no-quarkus-oidc-token-propagation[] io.quarkus quarkus-rest ---- -[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"] .build.gradle +ifndef::no-quarkus-oidc-token-propagation[] +[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"] ---- implementation("io.quarkus:quarkus-oidc,rest-client-oidc-filter,rest-client-oidc-token-propagation,rest") ---- +endif::no-quarkus-oidc-token-propagation[] +ifdef::no-quarkus-oidc-token-propagation[] +[source,gradle,role="secondary asciidoc-tabs-target-sync-gradle"] +---- +implementation("io.quarkus:quarkus-oidc,rest-client-oidc-filter,rest") +---- +endif::no-quarkus-oidc-token-propagation[] == Writing the application @@ -155,11 +180,13 @@ public class ProtectedResource { `ProtectedResource` returns a name from both `userName()` and `adminName()` methods. The name is extracted from the current `JsonWebToken`. -Next, add three REST clients: +Next, add the following REST clients: 1. `RestClientWithOidcClientFilter`, which uses an OIDC client filter provided by the `quarkus-rest-client-oidc-filter` extension to get and propagate an access token. 2. `RestClientWithTokenHeaderParam`, which accepts a token already acquired by the programmatically created OidcClient as an HTTP `Authorization` header value. +ifndef::no-quarkus-oidc-token-propagation[] 3. `RestClientWithTokenPropagationFilter`, which uses an OIDC token propagation filter provided by the `quarkus-rest-client-oidc-token-propagation` extension to get and propagate an access token. +endif::no-quarkus-oidc-token-propagation[] Add the `RestClientWithOidcClientFilter` REST client: @@ -217,7 +244,7 @@ public interface RestClientWithTokenHeaderParam { @Produces("text/plain") @Path("userName") Uni getUserName(@HeaderParam("Authorization") String authorization); <1> - + @GET @Produces("text/plain") @Path("adminName") @@ -226,6 +253,7 @@ public interface RestClientWithTokenHeaderParam { ---- <1> `RestClientWithTokenHeaderParam` REST client expects that the tokens will be passed to it as HTTP `Authorization` header values. +ifndef::no-quarkus-oidc-token-propagation[] Add the `RestClientWithTokenPropagationFilter` REST client: [source,java] @@ -263,6 +291,8 @@ public interface RestClientWithTokenPropagationFilter { IMPORTANT: Do not use the `RestClientWithOidcClientFilter` and `RestClientWithTokenPropagationFilter` interfaces in the same REST client because they can conflict, leading to issues. For example, the OIDC client filter can override the token from the OIDC token propagation filter, or the propagation filter might not work correctly if it attempts to propagate a token when none is available, expecting the OIDC client filter to obtain a new token instead. +endif::no-quarkus-oidc-token-propagation[] + Also, add `OidcClientCreator` to create an OIDC client programmatically at startup. `OidcClientCreator` supports `RestClientWithTokenHeaderParam` REST client calls: @@ -340,12 +370,12 @@ public class FrontendResource { @Inject @RestClient RestClientWithOidcClientFilter restClientWithOidcClientFilter; <1> - + @Inject @RestClient RestClientWithTokenPropagationFilter restClientWithTokenPropagationFilter; <2> - @Inject + @Inject OidcClientCreator oidcClientCreator; TokensHelper tokenHelper = new TokensHelper(); <5> @Inject @@ -387,7 +417,7 @@ public class FrontendResource { return tokenHelper.getTokens(oidcClientCreator.getOidcClient()).onItem() .transformToUni(tokens -> restClientWithTokenHeaderParam.getUserName("Bearer " + tokens.getAccessToken())); } - + @GET @Path("admin-name-with-oidc-client-token-header-param") @Produces("text/plain") @@ -403,7 +433,7 @@ public class FrontendResource { Tokens tokens = tokenHelper.getTokens(oidcClientCreator.getOidcClient()).await().indefinitely(); return restClientWithTokenHeaderParam.getUserName("Bearer " + tokens.getAccessToken()).await().indefinitely(); } - + @GET @Path("admin-name-with-oidc-client-token-header-param-blocking") @Produces("text/plain") @@ -411,7 +441,7 @@ public class FrontendResource { Tokens tokens = tokenHelper.getTokens(oidcClientCreator.getOidcClient()).await().indefinitely(); return restClientWithTokenHeaderParam.getAdminName("Bearer " + tokens.getAccessToken()).await().indefinitely(); } - + } ---- <1> `FrontendResource` uses the injected `RestClientWithOidcClientFilter` REST client with the OIDC client filter to get and propagate an access token to `ProtectedResource` when either `/frontend/user-name-with-oidc-client-token` or `/frontend/admin-name-with-oidc-client-token` is called. @@ -663,7 +693,7 @@ curl -i -X GET \ In contrast with the preceding command, this command returns a `403` status code. -Next, test that the programmatically created OIDC client correctly acquires and propagates the token with `RestClientWithTokenHeaderParam` both in reactive and imperative (blocking) modes. +Next, test that the programmatically created OIDC client correctly acquires and propagates the token with `RestClientWithTokenHeaderParam` both in reactive and imperative (blocking) modes. Call the `/user-name-with-oidc-client-token-header-param`. This command returns the `200` status code and the name `alice`: diff --git a/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc b/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc index cb2ea8024881c..f89e79f8c1346 100644 --- a/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc +++ b/docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc @@ -410,6 +410,7 @@ After a little while, you can run this binary directly: == Test the application +ifndef::no-deprecated-test-resource[] === Use Dev Services for Keycloak xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] is recommended for the integration testing against Keycloak. @@ -562,6 +563,7 @@ public class CodeFlowIT extends CodeFlowTest { ---- For more information about how it is initialized and configured, see xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak]. +endif::no-deprecated-test-resource[] === Use the browser diff --git a/docs/src/main/asciidoc/security-overview.adoc b/docs/src/main/asciidoc/security-overview.adoc index 81217b8b412c1..9156d3fcbaece 100644 --- a/docs/src/main/asciidoc/security-overview.adoc +++ b/docs/src/main/asciidoc/security-overview.adoc @@ -17,8 +17,12 @@ Before building security into your Quarkus applications, learn about the xref:se == Key features of Quarkus Security The Quarkus Security framework provides built-in security authentication mechanisms for Basic, Form-based, and mutual TLS (mTLS) authentication. +ifndef::no-webauthn-authentication[] You can also use other well-known xref:security-authentication-mechanisms.adoc#other-supported-authentication-mechanisms[authentication mechanisms], such as OpenID Connect (OIDC) and WebAuthn. - +endif::no-webauthn-authentication[] +ifdef::no-webauthn-authentication[] +You can also use other well-known xref:security-authentication-mechanisms.adoc#other-supported-authentication-mechanisms[authentication mechanisms], such as OpenID Connect (OIDC). +endif::no-webauthn-authentication[] Authentication mechanisms depend on xref:security-identity-providers.adoc[Identity providers] to verify the authentication credentials and map them to a `SecurityIdentity` instance with the username, roles, original authentication credentials, and other attributes. {project-name} also includes built-in security to allow for role-based access control (RBAC) based on the common security annotations `@RolesAllowed`, `@DenyAll`, `@PermitAll` on REST endpoints, and Contexts and Dependency Injection (CDI) beans. @@ -77,11 +81,13 @@ For more information, see the Quarkus xref:security-csrf-prevention.adoc[Cross-S You can add a link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite[SameSite] cookie property to any of the cookies set by a Quarkus endpoint. For more information, see the xref:http-reference.adoc#same-site-cookie[SameSite cookies] section of the Quarkus "HTTP reference" guide. +ifndef::no-quarkiverse[] [[secrets-engines]] === Secrets engines You can use secrets engines with Quarkus to store, generate, or encrypt data. Quarkus provides additional extensions in Quarkiverse for securely storing credentials, for example, link:{vault-guide}[Quarkus and HashiCorp Vault]. +endif::no-quarkiverse[] == Secrets in environment properties diff --git a/docs/src/main/asciidoc/smallrye-graphql-client.adoc b/docs/src/main/asciidoc/smallrye-graphql-client.adoc index 4aa0a118e0d6b..bfe200446348c 100644 --- a/docs/src/main/asciidoc/smallrye-graphql-client.adoc +++ b/docs/src/main/asciidoc/smallrye-graphql-client.adoc @@ -363,7 +363,8 @@ This example showed how to use both the dynamic and typesafe GraphQL clients to GraphQL service and explained the difference between the client types. == References +ifndef::no-quarkus-oidc-client-graphql[] +* xref:security-openid-connect-client-reference.adoc#quarkus-oidc-client-graphql[Integrating OIDC clients into GraphQL clients] +endif::no-quarkus-oidc-client-graphql[] -* xref:security-openid-connect-client-reference.adoc#oidc-client-graphql-client[Integrating OIDC clients into GraphQL clients] * https://smallrye.io/smallrye-graphql/latest/[Upstream SmallRye GraphQL Client documentation] -