This plugin is based on the OAuth 2 RFC document and allows Glewlwyd to act as an OAuth2 Provider.
Note
This plugin is deprecated. If bugs are found they will be fixed, but you should use the OpenID Connect plugin instead.
It's recommened to use the OIDC plugin instead.
The following OAuth2 functionalities are supported:
- Authorization Code
- Implicit
- Resource Owner Password Credentials
- Client Credentials
- Refreshing an Access Token
- Proof Key for Code Exchange by OAuth Public Clients
- Token introspection (RFC 7662)
- Token revocation (RFC 7009)
- OAuth 2.0 Device Authorization Grant
Glewlwyd OAuth2 plugin uses JWTs as access tokens. Therefore, the access token can be used by the client or the third party web service to identify the user and the scopes available with this access token.
An access token payload has the following JSON format:
{
username: "user1", // Username that was provided this access_token
salt: "abcdxyz1234", // Random string to avoid collisions
type: "access_token", // Hardcoded
iat: 1466556840, // Issued at time in Epoch Unix format
expires_in: 3600, // Number of seconds of validity for this token
scope: "scope1 g_profile" // scopes granted to this access token in a string separated by spaces
}
To create a key/certificate pair in RSA or ECDSA format, run the following commands on a linux shell with openssl installed:
$ # RSA KEY
$ # private key
$ openssl genrsa -out private-rsa.key 4096
$ # public key
$ openssl rsa -in private-rsa.key -outform PEM -pubout -out public-rsa.pem
$ # ECDSA KEY
$ # private key
$ openssl ecparam -genkey -name secp521r1 -noout -out private-ecdsa.key
$ # public key
$ openssl ec -in private-ecdsa.key -pubout -out public-ecdsa.pem
For more information on keys generation, see OpenSSL Documentation.
In the administration page, go to Parameters/Plugins
and add a new plugin by clicking on the +
button. In the modal, enter a name and a display name (the name must be unique among all user backend instances).
Select the type Glewlwyd OAuth2 plugin
in the Type drop-down button.
Below is the definition of all parameters.
Name (identifier) of the plugin instance, must be unique among all the plugin instances, even of a different type.
Name of the instance displayed to the user.
Algorithm used to sign access tokens and ID Tokens.
The algorithm supported are RSA
and ECDSA
using a private and a public key, and SHA
using a shared secret.
Size of the key to sign the tokens. The sizes supported are 256 bits, 384 bits or 512 bits.
Private key file used to sign if the selected algorithm is RSA
or ECDSA
. Must be a PEM format file.
Shared secret if the selected algorithm is SHA
.
Public key file used to validate access tokens if the selected algorithm is RSA
or ECDSA
. Must be a PEM format file.
Duration of each access tokens. Default value is 3600 (1 hour).
Duration of validity of each refresh tokens. Default value is 1209600 (14 days).
Duration of validity of each code sent to the client before requesting a refresh token. Default value is 600 (10 minutes).
If this option is checked, every time an access token is requested using a refresh token, the refresh token issued at time will be reset to the current time. This option allows infinite validity for the refresh tokens if it's not manually disabled, but if a refresh token isn't used for more of the value Refresh token duration
, it will be disabled.
Enable response type code
.
If this option is set, when a code is replayed to gain a refresh token, all the refresh and access tokens delivered for this code will be revoked. This option can be used to mitigate replay attacks and enforce tokens security.
Enable response type token
.
Enable response type password
.
Enable response type client_credential
.
Enable response type refresh_token
.
This section allows to put specific settings for an scope that will override the plugin settings.
The settings that you can override are Refresh token duration
and/or Rolling refresh
.
Please note that a specific scope parameter has a higher priority than the plugin settings, and if have multiple scopes in a request that have specific settings, the settings will follow the following algorithm:
- Refresh token duration: The duration provided will be the lowest duration among all the specific scope parameters.
- Rolling refresh: The value
No
has higher priority, therefore rolling refresh provided will beNo
if one scope has the valueNo
,Yes
otherwise
This section allows to add specific values to the access_tokens that will be taken from the user property values.
You can add as many additional values as you want. If the property isn't present in the user data, it will be ignored. If the value is multiplier, all values will be present, separated by a comma ,
.
This section is used to configure Proof Key for Code Exchange by OAuth Public Clients.
Enable this feature if you want to support code challenge.
Enable this feature if you want to allow method plain
in the code challenge feature. It is not recommended to enable this feature unless you know what you do because this feature is slightly less secure than default method S256
.
According to the specifications:
Clients are
permitted to use "plain" only if they cannot support "S256" for some
technical reason and know via out-of-band configuration that the
server supports "plain".
IMPORTANT NOTICE!
Glewlwyd access tokens are JWTs, the original way for resource services to check if an access token is valid and reliable is to check its signature and its expiration date. Token introspection and revocation have been introduced in Glewlwyd, but if the resource service doesn't use the introspection endpoint, it will miss an inactive token and still consider it valid.
The endpoints /profile
, /introspect
and /revoke
when they are given an access token to authenticate will check if the token is revoked or not.
Enable this feature if you want your oauth2 instance to enable endpoints /introspect
and /revoke
.
Enable this feature if your want to allow clients to use endpoints /introspect
and /revoke
using their client_id and secret as HTTP Basic Auth. The clients will be allowed to introspect and revoke only the tokens that were issued for them.
Add on or more scopes if you want to allow to use endpoints /introspect
and /revoke
using valid access tokens to authenticate the requests. The access tokens must have the scopes required in their payload to be valid.
When you add or edit a client in Glewlwyd, you can set a client secret
or a password
. Both can be used to authenticate confidential clients.
The primary difference is that a client secret is a string stored 'as is' in the backend (database or LDAP), without hashing, where a client password is stored in a hashed form in the backend, so makes it more difficult for attackers to retrieve it.
A client secret has priority over a client password, which means that if a client has set both client secret and client password, the authentication will be executed with client secret only.
This document is intended to describe Glewlwyd OAuth 2 plugin implementation.
OAuth endpoints are used to authenticate the user, and to send tokens or other authentication and identification data. The complete specification is available in the OAuth 2 RFC document. If you see an issue or have a question on Glewlwyd OAuth 2 plugin implementation, you can open an issue or send an email to the following address [email protected].
- Endpoints authentication
- Prefix
- Login and grant URIs
- Scope
- OAuth 2 endpoints
- OAuth 2 schemes
- Manage refresh tokens endpoints
- Token introspection and revocation
Authentication has different faces, and differs with the authorization scheme.
All URIs are based on the prefix you will setup. In this document, all API endpoints will assume they use the prefix /api/glwd
, and all static file endpoints will assume they use the prefix /
.
In this document, the login URI will be displayed as http://login.html
, this will be replaced by the values from your environment that you can define in the config file.
This is a multi-method, multi-parameters, versatile endpoint, used to provide authentication management. It handles the following authorization schemes as describe in the OAuth 2 RFC document:
- Authorization Code Grant (Authorization part)
- Implicit Grant
/api/glwd/auth
GET
POST
This endpoint is used to provide tokens to the user. It handles the following authorization schemes as describe in the OAuth 2 RFC document:
- Authorization Code Grant (Access Token part)
- Resource Owner Password Credentials Grant
- Client Credentials Grant
- Refreshing a token
- Deleting a token
/api/glwd/token
POST
Each scheme is described in the following chapter. The description may not be as complete as the OAuth 2 RFC document, consider the RFC as the authority standard.
/api/glwd/auth
GET
POST
Required
`response_type`: text, must be set to `code`
`client_id`: text, client_id that sends the request on behalf of the resource owner, must be a valid client_id
`redirect_uri`: text, redirect_uri to send the resource owner to after the connection, must be a valid redirect_uri for the specified client_id
`scope`: text, scope list that the resource owner will grant access to the client, multiple scope values must be separated by a space
Optional
state
: text, an identifier used to prevent requests collisions and bypass, will be sent back as is to the client
Code 302
Resource owner is not authenticated with a valid session token.
Redirect to http://login.html?client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&additional_parameters
for authentication.
See login paragraph for details.
Code 302
Redirect to http://login.html?client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&additional_parameters
for grant access.
Code 302
Redirect to redirect_uri
?code=code
&state=state
with redirect_uri
specified in the request, a code
generated for the access, and the state specified in the request if any.
Scope is not allowed for this user
Code 302
Redirect to redirect_uri
?error=invalid_scope&state=state
with redirect_uri
specified in the request, invalid_scope
as error value, and the state specified in the request if any.
Client is invalid, redirect_uri is invalid for this client, or client is not allowed to use this scheme
Code 302
Redirect to redirect_uri
?error=unauthorized_client&state=state
with redirect_uri
specified in the request, unauthorized_client
as error value, and the state specified in the request if any.
/api/glwd/token
POST
If client_id
refers to a confidential client, then client_id and client_password must be sent via Basic HTTP Auth.
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
grant_type: text, must be set to "authorization_code".
code: text, required
redirect_uri: text, must be same redirect_uri used in the authorization request that sent back this code
client_id: text, must be the same client_id used in the authorization request that sent back this code
Code 200
Content
{
"access_token":text, jwt token
"token_type":text, value is "bearer",
"expires_in":number, set by server configuration
"refresh_token":text, jwt token
}
Code 400
Error input parameters
The combination code/redirect_uri/client_id is incorrect.
/api/glwd/auth
GET
Required
`response_type`: text, must be set to `token`
`client_id`: text, client_id that sends the request on behalf of the resource owner, must be a valid client_id
`redirect_uri`: text, redirect_uri to send the resource owner to after the connection, must be a valid redirect_uri for the specified client_id
`scope`: text, scope list that the resource owner will grant access to the client, multiple scope values must be separated by a space
Optional
state
: text, an identifier used to prevent requests collisions and bypass, will be sent back as is to the client
Code 302
Resource owner is not authenticated with a valid session token.
Redirect to http://login.html?client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&additional_parameters
for authentication.
See login paragraph for details.
Code 302
Redirect to http://grant.html?client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&additional_parameters
for grant access.
See grant paragraph for details.
Code 302
Redirect to redirect_uri
#token=token
&state=state
with redirect_uri
specified in the request, a code
generated for the access, and the state specified in the request if any.
Scope is not allowed for this user
Code 302
Redirect to redirect_uri
#error=invalid_scope&state=state
with redirect_uri
specified in the request, invalid_scope
as error value, and the state specified in the request if any.
Client is invalid, redirect_uri is invalid for this client, or client is not allowed to use this scheme
Code 302
Redirect to redirect_uri
#error=unauthorized_client&state=state
with redirect_uri
specified in the request, unauthorized_client
as error value, and the state specified in the request if any.
/api/glwd/token
POST
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
grant_type: text, must be set to "password".
username: text
password: text
scope: text
Code 200
Content
{
"access_token":text, jwt token
"token_type":text, value is "bearer",
"expires_in":number, set by server configuration
"refresh_token":text, jwt token
}
Code 403
username or password invalid.
/api/glwd/token
POST
HTTP Basic authentication with client_id/client_password credentials. Client_id must be set as confidential
Required
Optional
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
grant_type: text, must be set to "client_credentials".
scope: text
Code 200
Content
{
"access_token":text, jwt token
"token_type":text, value is "bearer",
"expires_in":number, set by server configuration
}
Code 403
Access denied
Send a new access_token based on a valid refresh_token
/api/glwd/token
POST
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
grant_type: text, must be set to "refresh_token".
refresh_token: text, a valid ref refresh_token, mandatory
scope: text, must the same scope or a sub scope of the scope used to provide the refresh_token, optional
Code 200
Content
{
"access_token":text, jwt token
"token_type":text, value is "bearer",
"expires_in":number, set by server configuration
}
Code 400
Error input parameters
Mark a refresh_token as invalid, to prevent further access_token to be generated
/api/glwd/token
POST
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
grant_type: text, must be set to "delete_token".
refresh_token: text, a valid refresh_token, mandatory
Code 200
Code 400
Error input parameters
The following endpoints require a valid session cookie to identify the user. If the user has the scope g_admin
, it's possible to impersonate a user with the optional query parameter ?username={username}
.
/api/glwd/profile/token
GET
Optional
`offset`: number, the offset to start the list, default 0
`limit`: number, the number of elements to return, default 100
`pattern`: text, a pattern to filter results, pattern will filter the properties `user_agent` or `issued_for`
`sort`: text, the column to order the results, values available are `authorization_type`, `client_id`, `issued_at`, `last_seen`, `expires_at`, `issued_for`, `user_agent`, `enabled` and `rolling_expiration`
`desc`: no value, is set, the column specified in the `sort` parameter will be orderd by descending order, otherwise ascending
Code 200
Content
[{
"token_hash": text, refresh token hash signature
"authorization_type": text, authorization type used to generate this refresh token, value can be "code" or "password"
"client_id": text, client_id this refresh token was sent to
"issued_at": number, date when this refresh token was issued, epoch time format
"expires_at": number, date when this refresh token will expire, epoch time format
"last_seen": number, last date when this refresh token was used to generate an access token, epoch time format
"rolling_expiration": boolean, wether this refresh token is a rolling token, i.e. its expiration date will be postponed on each use to generate a new access token
"issued_for": text, IP address of the device which requested this refresh token
"user_agent": text, user-agent of the device which requested this refresh token
"enabled": boolean, set to true if this refresh token is enabled, i.e. can be used to generate new access tokens, or not
}]
Code 403
Access denied
/api/glwd/profile/token/{token_hash}
DELETE
Required
`token_hash`: text, hash value of the refresh token to disable, must be url-encoded
Code 200
Code 403
Access denied
Code 404
Refresh token hash not found for this user
The endpoints POST
/introspect
and POST
/revoke
are implementations of the corresponding RFCs Token introspection and revocation and OAuth 2.0 Token Revocation.
Both of them rely on 2 distinct ways to authenticate:
- HTTP Basic Auth corresponding to the client credentials whose client the token was submitted
- Authorized Access Token that includes the required scopes for those endpoints
Both authentication methods are non exclusive and the administrator may enable or disable each of them.
/api/glwd/introspect
POST
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
token: text, the token to introspect, required
token_type_hint: text, optional, values available are 'access_token' or 'refresh_token'
Code 200
Content
Active token
{
"username": text, username the token was issued for, if any
"client_id": text, client the token was issued for, if any
"iat": number, epoch time when the token was issued
"nbf": number, epoch time when the token was issued
"exp": number, epoch time when the token will be (or is supposed to be) expired
"scope": text, scope list this token was emitted with, separated with spaces
"token_type": text, type of the token, values may be 'access_token' or 'refresh_token'
}
Code 401
Access denied
Code 400
Invalid parameters
/api/glwd/revoke
POST
Request body parameters must be encoded using the application/x-www-form-urlencoded
format.
token: text, the token to introspect, required
token_type_hint: text, optional, values available are 'access_token' or 'refresh_token'
Code 200
Code 401
Access denied
Code 400
Invalid parameters