Skip to content

Commit

Permalink
Merge pull request #18073 from sberyozkin/oidc_credentials_provider
Browse files Browse the repository at this point in the history
Update 'quarkus-oidc' and 'quarkus-oidc-client' to get secrets from CredentialsProvider
  • Loading branch information
sberyozkin authored Jun 25, 2021
2 parents 85c2e7f + 967dfd6 commit 659435d
Show file tree
Hide file tree
Showing 16 changed files with 373 additions and 31 deletions.
2 changes: 2 additions & 0 deletions docs/src/main/asciidoc/credentials-provider.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ by the following credentials consumer extensions:
* `reactive-db2-client`
* `reactive-mysql-client`
* `reactive-pg-client`
* `oidc`
* `oidc-client`
All extensions that rely on username/password authentication also allow setting configuration
properties in the `application.properties` as an alternative. But the `Credentials Provider` is the only option
Expand Down
74 changes: 64 additions & 10 deletions docs/src/main/asciidoc/security-openid-connect-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,28 @@ quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.secret=mysecret
----

or

[source,properties]
----
quarkus.oidc-client.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.client-secret.value=mysecret
----

or with the secret retrieved from a link:credentials-provider[CredentialsProvider]:

[source,properties]
----
quarkus.oidc-client.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
# This is a key which will be used to retrieve a secret from the map of credentails returned from CredentialsProvider
quarkus.oidc-client.credentials.client-secret.provider.key=mysecret-key
# Set it only if more than one CredentialsProvider can be registered
quarkus.oidc-client.credentials.client-secret.provider.name=oidc-credentials-provider
----

`client_secret_post`:

[source,properties]
Expand All @@ -372,32 +394,56 @@ quarkus.oidc-client.credentials.client-secret.method=post

`client_secret_jwt`:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow
# This is a token key identifier 'kid' header - set it if your OpenId Connect provider requires it,
quarkus.oidc.credentials.jwt.token-key-id=mykey
----

or with the secret retrieved from a link:credentials-provider[CredentialsProvider]:

[source,properties]
----
quarkus.oidc-client.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow
# This is a key which will be used to retrieve a secret from the map of credentails returned from CredentialsProvider
quarkus.oidc-client.credentials.jwt.secret-provider.key=mysecret-key
# Set it only if more than one CredentialsProvider can be registered
quarkus.oidc-client.credentials.jwt.secret-provider.name=oidc-credentials-provider
----

`private_key_jwt` with the PEM key file:

[source,properties]
----
quarkus.oidc-client.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.key-file=privateKey.pem
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.jwt.key-file=privateKey.pem
# This is a token key identifier 'kid' header - set it if your OpenId Connect provider requires it
quarkus.oidc.credentials.jwt.token-key-id=mykey
----

`private_key_jwt` with the key store file:

[source,properties]
----
quarkus.oidc-client.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc-client.client-id=quarkus-app
quarkus.oidc-client.credentials.jwt.key-store-file=keystore.jks
quarkus.oidc-client.credentials.jwt.key-store-password=mypassword
quarkus.oidc-client.credentials.jwt.key-password=mykeypassword
quarkus.oidc-client.credentials.jwt.key-id=mykey
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.jwt.key-store-file=keystore.jks
quarkus.oidc.credentials.jwt.key-store-password=mypassword
quarkus.oidc.credentials.jwt.key-password=mykeypassword
# Private key alias inside the keystore
quarkus.oidc.credentials.jwt.key-id=mykey
# This is a token key identifier 'kid' header - set it if your OpenId Connect provider requires it,
# Note it can be different to the `quarkus.oidc.credentials.jwt.key-id` value
quarkus.oidc.credentials.jwt.token-key-id=mykey
----

Using `client_secret_jwt` or `private_key_jwt` authentication methods ensures that no client secret goes over the wire.
Expand Down Expand Up @@ -525,6 +571,14 @@ quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".level=TRACE
quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientImpl".min-level=TRACE
----

Please enable `io.quarkus.oidc.client.runtime.OidcClientRecorder` `TRACE` level logging to see more details about the OidcClient initialization errors:

[source, properties]
----
quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientRecorder".level=TRACE
quarkus.log.category."io.quarkus.oidc.client.runtime.OidcClientRecorder".min-level=TRACE
----

== Token endpoint configuration

By default the token endpoint address is discovered by adding a `/.well-known/openid-configuration` path to the configured `quarkus.oidc-client.auth-server-url`.
Expand Down
109 changes: 109 additions & 0 deletions docs/src/main/asciidoc/security-openid-connect-web-authentication.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,107 @@ It applies to ID tokens but also to access tokens in a JWT format if the `web-ap
== Token Propagation
Please see link:security-openid-connect-client#token-propagation[Token Propagation] section about the Authorization Code Flow access token propagation to the downstream services.

[[oidc-provider-client-authentication]]
=== Oidc Provider Client Authentication

`quarkus.oidc.runtime.OidcProviderClient` is used when a remote request to an OpenId Connect Provider has to be done. It has to authenticate to the OpenId Connect Provider when the authorization code has to be exchanged for the ID, access and refresh tokens, when the ID and access tokens have to be refreshed or introspected.

All the https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication[OIDC Client Authentication] options are supported, for example:

`client_secret_basic`:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.secret=mysecret
----

or

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.client-secret.value=mysecret
----

or with the secret retrieved from a link:credentials-provider[CredentialsProvider]:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
# This is a key which will be used to retrieve a secret from the map of credentails returned from CredentialsProvider
quarkus.oidc.credentials.client-secret.provider.key=mysecret-key
# Set it only if more than one CredentialsProvider can be registered
quarkus.oidc.credentials.client-secret.provider.name=oidc-credentials-provider
----

`client_secret_post`:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.client-secret.value=mysecret
quarkus.oidc.credentials.client-secret.method=post
----

`client_secret_jwt`:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow
# This is a token key identifier 'kid' header - set it if your OpenId Connect provider requires it,
quarkus.oidc.credentials.jwt.token-key-id=mykey
----

or with the secret retrieved from a link:credentials-provider[CredentialsProvider]:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
# This is a key which will be used to retrieve a secret from the map of credentails returned from CredentialsProvider
quarkus.oidc.credentials.jwt.secret-provider.key=mysecret-key
# Set it only if more than one CredentialsProvider can be registered
quarkus.oidc.credentials.jwt.secret-provider.name=oidc-credentials-provider
----

`private_key_jwt` with the PEM key file:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.jwt.key-file=privateKey.pem
# This is a token key identifier 'kid' header - set it if your OpenId Connect provider requires it
quarkus.oidc.credentials.jwt.token-key-id=mykey
----

`private_key_jwt` with the key store file:

[source,properties]
----
quarkus.oidc.auth-server-url=http://localhost:8180/auth/realms/quarkus/
quarkus.oidc.client-id=quarkus-app
quarkus.oidc.credentials.jwt.key-store-file=keystore.jks
quarkus.oidc.credentials.jwt.key-store-password=mypassword
quarkus.oidc.credentials.jwt.key-password=mykeypassword
# Private key alias inside the keystore
quarkus.oidc.credentials.jwt.key-id=mykey
# This is a token key identifier 'kid' header - set it if your OpenId Connect provider requires it,
# Note it can be different to the `quarkus.oidc.credentials.jwt.key-id` value
quarkus.oidc.credentials.jwt.token-key-id=mykey
----

Using `client_secret_jwt` or `private_key_jwt` authentication methods ensures that no client secret goes over the wire.

[[integration-testing]]
== Testing

Expand Down Expand Up @@ -751,6 +852,14 @@ quarkus.log.category."io.quarkus.oidc.runtime.OidcProvider".level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.OidcProvider".min-level=TRACE
----

Please enable `io.quarkus.oidc.runtime.OidcRecorder` `TRACE` level logging to see more details about the OidcProvider client initialization errors:

[source, properties]
----
quarkus.log.category."io.quarkus.oidc.runtime.OidcRecorder".level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.OidcRecorder".min-level=TRACE
----

== Running behind a reverse proxy

OIDC authentication mechanism can be affected if your Quarkus application is running behind a reverse proxy/gateway/firewall when HTTP `Host` header may be reset to the internal IP address, HTTPS connection may be terminated, etc. For example, an authorization code flow `redirect_uri` parameter may be set to the internal host instead of the expected external one.
Expand Down
13 changes: 13 additions & 0 deletions docs/src/main/asciidoc/security-openid-connect.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,11 @@ Note it is also recommended to use `quarkus.oidc.token.audience` property to ver

Please see link:security-openid-connect-client#token-propagation[Token Propagation] section about the Bearer access token propagation to the downstream services.

[[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 link:security-openid-connect-web-authentication#oidc-provider-client-authentication[OidcProviderClient Authentication] for more information about all the supported authentication options.

[[integration-testing]]
== Testing

Expand Down Expand Up @@ -867,6 +872,14 @@ quarkus.log.category."io.quarkus.oidc.runtime.OidcProvider".level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.OidcProvider".min-level=TRACE
----

Please enable `io.quarkus.oidc.runtime.OidcRecorder` `TRACE` level logging to see more details about the OidcProvider client initialization errors:

[source, properties]
----
quarkus.log.category."io.quarkus.oidc.runtime.OidcRecorder".level=TRACE
quarkus.log.category."io.quarkus.oidc.runtime.OidcRecorder".min-level=TRACE
----

== External and Internal Access to OpenId Connect Provider

Note that the OpenId Connect Provider externally accessible token and other endpoints may have different HTTP(S) URLs compared to the URLs auto-discovered or configured relative to `quarkus.oidc.auth-server-url` internal URL. For example, if your SPA acquires a token from an external token endpoint address and sends it to Quarkus as a Bearer token then an issuer verification failure may be reported by the endpoint.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public class OidcClientCredentialsJwtSecretTestCase {

private static Class<?>[] testClasses = {
OidcClientsResource.class,
ProtectedResource.class
ProtectedResource.class,
SecretProvider.class
};

@RegisterExtension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public class OidcClientCredentialsTestCase {

private static Class<?>[] testClasses = {
OidcClientsResource.class,
ProtectedResource.class
ProtectedResource.class,
SecretProvider.class
};

@RegisterExtension
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.quarkus.oidc.client;

import java.util.HashMap;
import java.util.Map;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;

import io.quarkus.arc.Unremovable;
import io.quarkus.credentials.CredentialsProvider;

@ApplicationScoped
@Unremovable
@Named("vault-secret-provider")
public class SecretProvider implements CredentialsProvider {

@Override
public Map<String, String> getCredentials(String credentialsProviderName) {
Map<String, String> creds = new HashMap<>();
creds.put("secret-from-vault", "secret");
creds.put("secret-from-vault-for-jwt",
"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow");
return creds;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ quarkus.oidc.client-id=quarkus-app
quarkus.oidc-client.client-enabled=false
quarkus.oidc-client.jwt.auth-server-url=${quarkus.oidc.auth-server-url}
quarkus.oidc-client.jwt.client-id=${quarkus.oidc.client-id}
quarkus.oidc-client.jwt.credentials.jwt.secret=AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow
quarkus.oidc-client.jwt.credentials.jwt.secret-provider.key=secret-from-vault-for-jwt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ quarkus.oidc.credentials.secret=secret

quarkus.oidc-client.auth-server-url=${quarkus.oidc.auth-server-url}
quarkus.oidc-client.client-id=${quarkus.oidc.client-id}
quarkus.oidc-client.credentials.secret=${quarkus.oidc.credentials.secret}
quarkus.oidc-client.credentials.client-secret.provider.name=vault-secret-provider
quarkus.oidc-client.credentials.client-secret.provider.key=secret-from-vault
4 changes: 4 additions & 0 deletions extensions/oidc-common/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-credentials-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-jwt-build-deployment</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions extensions/oidc-common/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-vertx-http</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-credentials</artifactId>
</dependency>
<dependency>
<groupId>io.smallrye.reactive</groupId>
<artifactId>smallrye-mutiny-vertx-web-client</artifactId>
Expand Down
Loading

0 comments on commit 659435d

Please sign in to comment.