Use case
It should be ensured that the end-user is well able to access protected resources, whether personal data or the application owns the data. We also want to be able to control the data transmitted by a protected resource to an application based on the rights of the end user in this application.
Administrators as well as end users will use OpenID Connect to authenticate to an application. We will want to modulate the rights and privileges of the end user according to his identity, his membership or his profile. The simplest example is the distinction between data read rights and edit rights. One can also consider assigning the user administrative rights to all or part of an application.
This is not the role of the authentication server, which must be transparent with respect to the authorization scopes implemented by an application. For this, OAuthSD allows an external application to incorporate additional declarations to JWT tokens, whether it is a JWT-format access token or an identity token. Protected resources "will know how to" interpret JWT data to control their response.
Note on data security
Recall that the payload of the JWT token is not encrypted, but only "URL64-encoded". Therefore, sensitive data should not be transmitted in this way.
The advantage of passing additional data into the payload of the JWT token is to unmistakably bind them using the signature to the identity of the client and to the user. This is particularly relevant for passing the privileges of a user or application to a protected resource. With this in mind, we can :
directly transmit the privileges ; for example a role that would take values such as ’administrator’, ’editor’, ’owner’, ’user’, etc., or any other code understood by the resource,
or transmit the user information that will allow the protected resource to establish its privileges.
But be careful in this second case : it should not reveal sensitive data on the user. If transmission of such data to the protected resource is required, the protected resource can query the Userinfo service.
One could think of an encrypted token (JWE), but it would require, besides a specific development, to deviate from the standard OpenID Connect. It would be much simpler to encrypt the additional information in one block and pass it into a single statement.
Passing end-user privileges with authentication
OAuthSD offers two complementary methods for incorporating information about an end user into the JWT :
writing additional data in the ’profile’ and ’scope’ fields of the users table using HTTP Rest service. This is an asynchronous process because the data is written at a time chosen by an external application, regardless of the authorization server query.
OAuthSD uses the scope ’privileges’ to control access to this information. When an application presents this scope in the authorization request, the ’profile’ and ’scope’ declarations are entered in the Userinfo response and in the JWT token payload.
Incorporating additional data refreshed when building the JWT token, for example by querying an external service. It is a synchronous process or "dynamic scope", to obtain information in phase with those held by the user management applications in the case where this management is external to the server.
This second method is developed now.
Incorporation of fresh additional data in JWT payload
This feature is specific to using OAuthSD in a group of applications controlled by the same organization (Corporate Realm).
The oauth2-server-php library provides a reconfigurable function for inserting additional declarations into a JWT at the time it is created.
To incorporate additional data, you must :
Set the EXTRA_PAYLOAD configuration constant to ’true’.
define the contents of the private_payload () function of the file /commons/oidc/interface/privatepayload.php.
The private_payload () function must be written by the application designer. It can be a call to a third party web-service. The function receives the parameters client_id, user_id and scope and must return a ’claim’ => ’value’ array which will be combined with the payload declarations without replacing the standard declarations.
Notes :
This method allows you to create declarations with any name. However, the OIDC standard declarations (’id’, ’jti’, ’iss’, ’aud’, ’sub’, ’exp’, ’iat’, ’token_type’ and ’scope’) can not be overloaded : they will keep their name and their value. For instance, if a ’scope’ declaration is returned, it will be incorporated into the JWT payload as "extra_scope".
The information is refreshed when the JWT token is created or refreshed. This implies that this information is not strictly synchronous with its corresponding in the external system. If a user’s rights change in the external system, it will be necessary to revoke the user’s session in order to trigger a new authentication request which will result in the creation of a new JWT token. But in the case where it would be necessary to change a large number of users, another way to ensure synchronism will be to close the service over the life of a JWT.
This method does not write in the users table and, in particular, in the "scope" field. If the additional declarations include a "scope" declaration (which will usually be the case), the value of the "scope" field of the users table will be incorporated into the JWT payload under the name "user_scope".
In any case, the value of the ’scope’ parameter passed to the authorize call by the application will be embedded under the name ’requested_scope’ [1].
See under the code for an example that retrieves additional data from a Web service.