[PREVIEW] Add the ability to specify that the OIDC Authentication Request should include request and request_uri parameters
Overview
OpenID Connect is an authentication mechanism that builds on OAuth 2.0 and allows a user to login to a web application using credentials established by an OpenID provider. Authentication requests sent using OpenID Connect can be signed and optionally encrypted by encoding query parameters in a JWT. This can be achieved using one of two auth request parameters: request
and request_uri
, which are both optional. The current version of elytron-oidc-client
does not allow the user to specify request
or request_uri
. Instead, all requests are sent in using the OAuth 2.0 request syntax.
This RFE will add an attribute to the elytron-oidc-client
subsystem called authentication-request-format
, which can allow the user to specify if they will use either of the request parameters. Additionally, we will be adding supporting attributes called request-object-signing-algorithm
, request-object-encryption-alg-value
and request-object-encryption-enc-value
, which will be used to specify if and how the request parameters will be signed and/or encrypted. All of these attributes will be added to the secure-server
, secure-deployment
, provider
and realm
resources, which the user can configure using either the elytron-oidc-client
subsystem, or using a json file in deployment configuration.
We will also be adding some keystore attributes, such as, request-object-signing-keystore-file
, request-object-signing-keystore-password
, request-object-signing-key-password
, request-object-signing-key-alias
and request-object-signing-keystore-type
to the resources mentioned above. There are similar attributes that are currently available under the credential
attribute. However, when they are configured outside of the credentials
attribute, they will be used to sign Request Objects.
According to the OpenID docs, requests using request
and request_uri
parameters are represented as JWTs, which are respectively passed by value or by reference. Depending on the OpenID Provider, support for these parameters may or may not be available.
Issue Metadata
Issue
Related Issues
Stability Level
-
Experimental
-
Preview
-
Community
-
default
Dev Contacts
QE Contacts
Testing By
-
Engineering
-
QE
Affected Projects or Components
-
WildFly
-
WildFly Elytron
Other Interested Projects
N/A
Relevant Installation Types
-
Traditional standalone server (unzipped or provisioned by Galleon)
-
Managed domain
-
OpenShift s2i
-
Bootable jar
Requirements
Hard Requirements
-
Some new attributes named
authentication-request-format
,request-object-signing-algorithm
,request-object-encryption-alg-value
andrequest-object-encryption-enc-value
will be added to thesecure-deployment
,secure-server
,realm
andprovider
resources under theelytron-oidc-client
subsystem. The value for theauthentication-request-format
attribute will be a String with 3 acceptable values:-
oauth2: Indicating that the query parameters will be sent as usual following the oauth2 syntax.
-
request: Indicating that the query will be sent as a JWT by value.
-
request_uri: Indicating that the query will be sent as a reference to the JWT.
-
-
The
authentication-request-format
attribute will specify if eitherrequest
or therequest_uri
should be added to the auth request. This will be an optional attribute. The default value for this attribute will be set tooauth2
, indicating that the request parameters will be sent regularly following the OAuth2 syntax.-
For multiple
secure-server
orsecure-deployment
resources using the samerealm
orprovider
, theauthentication-request-format
can be specified at the higher level resource, such as,provider
orrealm
. -
For multiple
secure-server
orsecure-deployment
resources using the same higher level resource, if the Request Object type is not the same for each deployment, then theauthentication-request-format
attribute can be set accordingly for the individual lower level resources.
-
-
According to the OIDC specs, only one of the two parameters can be specified at a time. If
request
is added, thenrequest_uri
MUST NOT be used in the same request. However, the user can choose to specify neither by settingauthentication-request-format
tooauth2
or not setting it at all. -
The
request
andrequest_uri
parameters MUST NOT be included in Request Objects. -
The Request Object MAY be signed or unsigned (plaintext) and can be specified by value or by reference. The user can specify the algorithm used to sign the JWT request using the
request-object-signing-algorithm
attribute which will also be added to the resources specified above. This algorithm must be one of the Request Object signature algorithms supported by the OpenID provider.-
The values for
request-object-signing-algorithm
attribute are of typeString
. Default value for this attribute would benone
, specifying that the request would be sent as a plaintext. In order to sign the jwt using an algorithm other thannone
, the user must specify the KeyPair used. This can be done using therequest-object-signing-keystore-file
,request-object-signing-keystore-password
,request-object-signing-key-password
,request-object-signing-key-alias
andrequest-object-signing-keystore-type
attributes. The algorithm for the KeyPair must match the algorithm used to sign the JWT. The keystore should be of typeJKS
or typePKCS12
and can be generated usingkeytool
on the linux terminal. -
The certificate for the KeyPair used to sign the JWT must be shared with the OpenID provider either by importing it from the keystore, or by uploading a jwksUrl.
-
When configuring the client in deployment or subsystem settings, the
public-client
attribute must be set tofalse
and client credentials must be specified as well using thecredentials
attribute. Client keys must be uploaded to the admin console of the OpenID Provider.
-
-
The request object may also be encrypted. To specify that the Request Object will be encrypted, the user needs to specify the relevant algorithms using
request-object-encryption-alg-value
andrequest-object-encryption-enc-value
. Encryption is done using JWE.-
The values for the
request-object-encryption-alg-value
and therequest-object-encryption-enc-value
attributes are of typeString
. The default value for the attributes are undefined, which specifies that the request object will not be encrypted. -
The request object will only be encrypted if both
request-object-encryption-alg-value
andrequest-object-encryption-enc-value
are specified. The values for these attributes must be part of the encryption algorithms and content encryption methods supported by the OpenID provider. These values can also be found by sending a GET request to the discovery url or by looking at the client configurations on the admin console of the OpenID provider. An example of what the GET request would return can be seen below (diaplaying attributes relevant to Request Objects only):
-
...
"request_object_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"request_object_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"request_object_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],
...
"request_parameter_supported":true,"request_uri_parameter_supported":true,"require_request_uri_registration":true,
...
-
The JWT must be signed first and then encrypted to make a nested JWT and the key used to encrypt the JWT must be the realm public key shared by the OpenID provider. The key algorithm must be the same as the encrypting algorithm. Signing and encrypting algorithms can be of different types (i. e. ES-256 for signing and RSA-OAEP for encrypting is allowed). The realm key for encrypting the JWT can be obtained by sending a GET request to the
jwksUri
obtained from thediscoveryUrl
(http://localhost:8080/realms/myrealm/.well-known/openid-configuration). For more information about how Keycloak supports Request Object Encryption, please refer to this issue and the following changes made to the Keycloak source code: -
An example of the attributes obtained from the
jwksUri
of an OpenID provider can be seen below. Please note that the actual values for some of the fields have been truncated for readability:
{"keys":[
{"kid":"I0ogHMugKrowsGS5StX8Ihx1qKSaH3QLVHl6FsVSVxE",
"kty":"RSA",
"alg":"RSA-OAEP",
"use":"enc",
"n":"vAHUwV28fDBXQpo390nm...",
"e":"AQAB",
"x5c":["MIICnTCCAYUCBgG..."],
"x5t":"EE4X1HpptqoAkDqMokwRwqliJFY","x5t#S256":"bfhIzItRxe9PKE7uPUJMpP4A-AozTWxMVPNwbzUhs2Y"},
{"kid":"TSLvxRZEuxTmFgYdrs3ve7-0-DghC-ChN724HB2fGOc",
"kty":"RSA",
"alg":"RS256",
"use":"sig","n":"jL35-5e67PukEk_...",
"e":"AQAB",
"x5c":["MIICnTCCAYUCBgGL..."],
"x5t":"hNGOdZ0Nszq4Oqj1TB-usasLP1I","x5t#S256":"KNsx334iBpN5oPEEYSCf1Q-TlmG69AOUghRRFa9VuWY"}
]}
-
The authentication request can send the Request Object in one of two ways:
-
By value: The
request
parameter is added to the query and its value is the Request Object itself. -
The request string can be added to the auth request by adding the whole string:
-
http://localhost:8080/realms/myrealm/protocol/openid-connect/auth?
response_type=code&
client_id=wildfly&
scope=openid&
redirect_uri=http%3A%2F%2Flocalhost%3A8090%2Fsimple-webapp-oidc%2Fsecured&
request=eyJhbGciOiJSU0EtT0FFUCI...
-
By reference: This is useful when the
request
string is too large and a number of other reasons. In this case, the Request Object is passed as a reference parameter string using therequest_uri
parameter. The url references the Request Object, which the OpenID provider can use to download the Request Object itself. The entire Request_URI MUST NOT exceed 512 ASCII characters. -
The
request_uri
value can be obtained by sending POST request to thepushed_authentication_request_endpoint
of the OpenID provider. This can be also obtained using the discoveryUrl. The content for the POST request contains the value of the signed and/or encrypted Request Object and the content type for this request is "application/x-www-form-urlencoded". -
Please see the following resources for more information on Keycloak’s implemetation of PAR.
-
A successful request will return 201 http code along with a JWT, which contains the value of the
request_uri
and its expiry time. -
When included in the auth request, the request_uri would be specified as:
http://localhost:8080/realms/myrealm/protocol/openid-connect/auth?
response_type=code&
client_id=wildfly&
scope=openid&
request_uri=urn%3Aietf%3Aparams%3Aoauth%3Arequest_uri%3Ad11a6442-d9ca-4db8-a885-f9f43673f859&
redirect_uri=http%3A%2F%2Flocalhost%3A8090%2Fsimple-webapp-oidc%2Fsecured
-
The base64-encoded SHA-256 hash
23GkurKxf5T0Y-mnPFCHqWOMiZi4VS138cQO_V7PZHAdM
will allow the provider to cache the token for future use. It is a hash of the contents of the Request Object.-
According to the OpenID docs, if the same parameter exists both in the Request Object and the OAuth Authorization Request parameters, the parameter in the Request Object is used.
-
The feature must deal with cases where the OpenId Provider does not support request parameters by recognizing
request_not_supported
error and dealing with it accordingly. -
It should be possible to specify that these parameters should be included in the Authentication Request via deployment configuration using the
oidc.json
file inside theWEB-INF
directory of the web application andelytron-oidc-client
subsystem configuration.
-
The request
attribute is specified through the deployment configuration as follows:
{
"client-id" : "myclient",
"provider-url" : "${env.OIDC_PROVIDER_URL:http://localhost:8080}/realms/myrealm",
"public-client" : "false",
"authentication-request-format" : "request",
"principal-attribute" : "preferred_username",
"ssl-required" : "EXTERNAL"
"credentials" : {
"secret" : "CLIENT_SECRET"
}
}
The request
attribute is specified through the elytron-oidc-client
subsystem as follows:
/subsystem=elytron-oidc-client/secure-deployment:add(client_id=myclient, provider-url="http://localhost:8090/", authentication-request-format="request")
The request_uri
attribute is specified through the deployment configuration as follows:
{
"client-id" : "myclient",
"provider-url" : "${env.OIDC_PROVIDER_URL:http://localhost:8080}/realms/myrealm",
"public-client" : "false",
"authentication-request-format" : "request_uri",
"principal-attribute" : "preferred_username",
"ssl-required" : "EXTERNAL"
"credentials" : {
"secret" : "CLIENT_SECRET"
}
}
The request
attribute is specified through the elytron-oidc-client
subsystem as follows:
/subsystem=elytron-oidc-client/secure-deployment:add(client_id=myclient, provider-url="http://localhost:8090/", authentication-request-format="request_uri")
Nice-to-Have Requirements
N/A
Non-Requirements
N/A
Backwards Compatibility
N/A
Default Configuration
By default, neither request
or request_uri
would be specified and the value for authentication-request-format
would be oauth2
.
Test Plan
-
WildFly Elytron Tests: Integration test cases implemented for functionality.
-
WildFly Testsuite: Test cases will be added to check for subsystem parsing.
-
Additional integration tests will be added to test the full functionality of the
elytron-oidc-subsystem
whenrequest
orrequest_uri
are configured. -
Tests will be performed using signed (using symmetric and asymmetric keys), unsigned, encrypted and plaintext JWT requests, with the request specified both by value and by reference.
-
-
Tests will be added for both subsystem and deployment configurations.
-
Tests may be added to ensure that server configuration fails when the stability level is not specified appropriately.
Community Documentation
Documentation for the new request
and request_uri
attributes will be added to Elytron OpenID Connect Client Subsystem Configuration.
Release Note Content
This feature allows authentication requests to be sent as a signed and encrypted request object using request and request_uris.