OAuth2 authorization
OAuth2 authorization is being implemented in DIRAC for transitioning to using access tokens to manage jobs and data, and for simplifying the authorization process for users.
The main goal
The main goal is to expand the capabilities of DIRAC in terms of interoperability with third-party systems that support OAuth 2 authorization. Enabling users to access DIRAC resources not only through a proxy certificate, but also with access tokens obtained through Identity Providers.
OAuth 2.0 framework
The OAuth 2.0 authorization framework is a protocol that allows a user to grant a third-party web site or application access to the user’s protected resources, without necessarily revealing their long-term credentials or even their identity. There are already many articles to familiarize yourself with this framework, for example Auth0 Docs or RFCs
The following diagram shows the main OAuth 2.0 roles in DIRAC.
A feature of DIRAC is the ability to perform user tasks asynchronously on behalf of the user, i.e. using their access token or proxy certificate.
As shown in the figure, DIRAC server components, such as service or agent, may have sufficient privileges to request a user access token (or proxy). Upon receiving it, the component can access the protected resource on behalf of the user.
Warning
The OAuth 2.0 scheme does not involve the use of X509 certificates, but since their usage is still mandatory in DIRAC, the scheme is more complicated: the protected resource request may contain the X509 proxy user certificate instead of the user access token.
OAuth 2.0 roles
An OAuth 2.0 flow has the following roles:
Resource Owner - Entity that can grant access to a protected resource. In the context of DIRAC, these are DIRAC users.
Resource Server - Server hosting the protected resources. In the context of DIRAC, this is DIRAC backend components like a DIRAC services.
Client - Application requesting access to a protected resource on behalf of the Resource Owner. In the context of DIRAC, these are DIRAC client installations. The client may also be a DIRAC component, such as a service or agent, that uses a user access token to access DIRAC services.
Authorization Server - Server that authenticates the Resource Owner and issues access tokens after getting proper authorization. In the context of DIRAC, this is DIRAC Authorization Server.
OAuth 2.0 grants
OAuth 2.0 defines flows to get an access token, called grant types. We use the following flows:
Device Flow to authorize with DIRAC client installation.
Authorization Code Flow to authorize with browser.
Client Credentials to authorize Web portal and to interact with third party authorization services.
Refresh Token to implement long sessions for DIRAC clients and to refresh users access tokens.
Token Exchange to get access tokens from third party Identity Providers with scope needed for a particular case.
Warning
DIRAC components can use the host certificate as Client Credentials, which goes beyond the OAuth 2.0 scheme.
Involved components
DIRAC Authorization Server (AS) - acts as an authorization server for DIRAC clients by providing users with access tokens and proxies
command line interface (CLI) - commands for creating a DIRAC work session, see dirac-login, dirac-logout, dirac-configure.
Authorization API endpoints - OAuth2 endpoints for authorization, receiving a response from Identity Provider, obtaining an access token, etc., see
AuthHandler
.Token Manager (TM) service - Service that takes care of storing, updating and obtaining new user access tokens. Similar to the Proxy Manager service, but differs in the specifics of working with tokens.
Identity Provider (IdP) - a type of DIRAC resource that allows you to describe the interaction with third-party services that manage user accounts.
also the tornado framework containing the logic of authorizing client requests to DIRAC components, which in turn act as a resource.
DIRAC Authorization Server
This component is based on the popular authlib python3 library.
The necessary components for DIRAC Authorization Server to work are collected in a authorization
subpackage.
Components
grants
contains helper classes with descriptions of the flows to get and revoke an access token.
utils
contains helper classes with main OAuth2 object descriptions and helper methods.
AuthServer
inherits from authlib.oauth2.AuthorizationServer and simulates the operation of OAuth 2 authorization server.
Configuration
Authorization Server metadata:
DIRAC AS should contain a metadata that an OAuth client can use to obtain the information needed to interact with DIRAC AS, including its endpoint locations and authorization server capabilities. But you don’t have to worry about that, just define the /DIRAC/Security/Authorization/issuer option in the DIRAC configuration, and everything else will be determined for you by the
collectMetadata()
method.
Authorization clients:
OAuth defines two types of clients:
confidential clients
public clients
DIRAC AS takes both into account and already has a default public client (see
Clients
) configured to authorize DIRAC client installations via the device code authorization flow mentioned earlier. The new authorization client metadata can be described in the /DIRAC/Security/Authorization/Clients section in format:CLIENT_NAME { client_id=MY_CLIENT_ID client_secret=MY_CLIENT_SECRET scope=supported scopes separated by a space response_types=device, grant_types=refresh_token, }
Supported scopes:
For DIRAC-specific authorization, support for the following scopes is implemented:
g:<DIRAC group name> this parametric scope allows you to notify which group the user selects when logging in.
proxy scope informs that the user expects to receive a proxy certificate instead of a token after successful authorization.
lifetime:<proxy life time in a seconds> scope informs how long the proxy should be.
Commands
Two commands were created for interaction with DIRAC AS:
Also added the ability to authorize without a certificate while configuring the DIRAC client with the dirac-configure command and a special --login
flag.
Authorization API
With a new system component - APIs, was created Authorization API for Framework system (see AuthHandler
) which provides the necessary endpoints for interaction with DIRAC AS.
Token Manager
The Token Manager service aims to capture access tokens and refresh user tokens upon successful authorization and manage them, issue access tokens upon request of DIRAC services or user-owners.
Identity Provider
Since DIRAC is not going to perform the function of user account management, it delegates this function as much as possible to third parties services where VOs should be registered and where there are VO administrators who will deal with it. Such resources are described as IdProviders, see Identity Provider.
Tornado Framework
The framework has also been modified, adding the ability to access DIRAC services using access tokens, see TornadoBaseClient
and BaseRequestHandler
.
Note
to use the received access token to access DIRAC services, you need to add /DIRAC/Security/UseTokens=true
or export DIRAC_USE_ACCESS_TOKEN=true
.
Logging in
Consider process by which an user gains access to a DIRAC resources by identifying and authenticating themselves.
DIRAC CLI
The dirac-login
command will help us with this. There are three main ways to authorize:
using a local user certificate to obtain a proxy certificate
logging in with DIRAC AS to obtain a proxy certificate
logging in with DIRAC AS to obtain an access token
Using dirac-login my_group --use-certificate
:
- Using the local certificate
dirac-login
makes a similar algorithm as dirac-proxy-init: Generate a proxy certificate locally on the user’s machine from a locally installed user certificate.
Try to connect to the DIRAC Configuration Server (CS) with this proxy certificate.
If the connection was successful, a command generate a proxy certificate with the required extensions.
A proxy certificate without extensions upload to
ProxyDB
usingProxyManagerHandler
.
Using dirac-login my_group --use-diracas --token
:
User do not need to have a locally installed certificate if logging in through DIRAC AS.
dirac-login
initializes OAuth 2.0 Device flow by passing DIRAC client ID to DIRAC AS.DIRAC AS responds with a
device_code
,user_code
,verification_uri
,verification_uri_complete
,expires_in
(lifetime in seconds for device_code and user_code), and pollinginterval
.The command asks the user to log in using a device that has a browser(e.g.: their computer, smartphone) or if the device running
dirac-login
has a browser installed, a new tab with the received URL will open automatically.
The command begins polling DIRAC AS for an access token sending requests to token endpoint until either the user completes the browser flow path or the user code expires.
After receiving this request from the browser, DIRAC AS will initialize OAuth 2.0 Authorization Code flow with choosed IdP. If several IdPs are registered in DIRAC and it is not clear from the requested group which one to choose, DIRAC AS will ask the user to choose one.
DIRAC AS prepare authorization URL for the corresponding IdP and redirects the user to the login and authorization prompt.
When the user has successfully logged in, IdP redirects him back to the DIRAC AS with an authorization code.
DIRAC AS sends this code to the IdP along with the client credentials and recieve an ID token, access token and refresh token.
DIRAC AS try to parse received tokens to get the user profile and its ID.
Check whether the ID is registered in the DIRAC CS Registry, if not then the authorization process is interrupted and administrators receive a message about an unregistered user.
If the user is registered,
TokenManagerHandler
stores tokens inTokenDB
.If
TokenDB
already contains tokens for the user, then the extra tokens are revoked (just one refresh token in Token Manager for the user is enough).
DIRAC AS update authorization session status.
Here we back to OAuth 2.0 Device flow. Upon receipt of a request for an access token, DIRAC AS requests
TokenManagerHandler
to provide a fresh access token to the requested user and group.
Token Manager forms a scope that corresponds to the selected group.
After that Token Manager makes aexchange token request to get new access and refresh tokens.
DIRAC AS encrypts the refresh token and stores it in
AuthDB
.DIRAC AS responds with an access and encripted refresh token.
Using dirac-login my_group --use-diracas --proxy
:
- In this case, the process differs only in that when the user successfully completes the browser flow path, DIRAC AS responds with a proxy:
Upon receipt of a request for a proxy, DIRAC AS requests
ProxyManagerHandler
to provide a proxy to the requested user and group.
Proxy Manager see if you need a VOMS extension for the selected group.
Proxy Manager makes
voms-proxy-init
with the required flags if a VOMS extension is required and add DIRAC group extension.DIRAC AS responds with a proxy.
Web portal
- The diagram shows the following steps:
The user selects an identity provider for authorization in the web portal.
After receiving this request from the browser, the web server creates an authorization session, and redirects the user to DIRAC AS by initiating the OAuth 2.0 Authorization Code flow.
DIRAC AS will initialize OAuth 2.0 Authorization Code flow with choosed IdP.
When the user has successfully logged in, DIRAC AS redirects him back to the web server with an authorization code.
Web server sends this code to the DIRAC AS along with the client credentials and recieve an access and refresh tokens.
The web server creates an http only secure cookie with the received tokens and store an access token in sessionStorage (see https://www.w3schools.com/jsref/prop_win_sessionstorage.asp for more details). This token can be used by JS code from the user’s browser (currently not used).
This scheme is being revised to simplify it.
Logging out
Consider process by which an user end work session with DIRAC.
DIRAC CLI
Using dirac-logout
:
- If it is a long session, i.e. with a refresh token, which allows you to update the access token and thus continue the working session, then to end the session it is necessary to revoke the refresh token:
dirac-logout sends a revoke request to DIRAC AS.
DIRAC AS decrypts the refresh token and reads to whom it belongs.
DIRAC AS makes a revoke request to the appropriate IdP.
DIRAC AS removes the record about this refresh token from the
AuthDB
database.
Delete the token file.
Web portal
Click on the username to select “Log out”.
The web server receives a request from the user’s browser to end the session and made revoke refresh token request to DIRAC AS. After that cleans cookies.