Iddawc
Handle the flow of OAuth2 and OpenID Connect authentication process from the client side.
|
Iddawc is a C library used to implement OAuth2/OIDC clients according to the OAuth2 RFC and the OpenID Connect Specs.
It's based on Ulfius library for the HTTP requests and response management and Rhonabwy library for the JOSE management.
Iddawc supports the following features:
auth
requests using the given parameters (client_id
, client_secret
, redirect_uri
, etc.) and parsing the resulttoken
requests using the given parameters (code
, client_id
, client_secret
, redirect_uri
, etc.) and parsing the resultuserinfo
, token introspection
, token revocation
requestsregister
endpoint if anyauth
and token
endpointsLots of functions in Rhonabwy library return an int value. The returned value can be one of the following:
If a function is successful, it will return I_OK
(0), otherwise an error code is returned.
It's recommended to use i_global_init
and i_global_close
at the beginning and at the end of your program to initialize and cleanup internal values and settings. This will make outgoing requests faster, especially if you use lots of them, and dispatch your memory allocation functions in curl and Jansson if you changed them. These functions are NOT thread-safe, so you must use them in a single thread context.
Usually, a log message is displayed to explain more specifically what happened on error. The log manager used is Yder. You can enable Yder log messages on the console with the following command at the beginning of your program:
Example of an error log message:
Go to Yder API Documentation for more details.
Iddawc is based in the struct _i_session
to store all the required parameters and results to work. You must use the init and clean functions before using a struct _i_session *
and after finishing using it.
To set or get parameters stored in the struct _i_session *
, you must use the appropriate function
Iddawc supports importing or exporting struct _i_session *
. The export format is JSON
. Be careful, the JSON output is unsecured and contains all secrets and tokens without encryption!
You can import and export either in json_t *
or char *
, the char *
format is a JSON stringified.
Finally, to run OAuth2 or OIDC requests, you must use the dedicated functions using the initialized and set struct _i_session *
and some additional parameters if required.
When available, you can load the Openid Config endpoint. This will parse the result and fill the struct _i_session *
parameters with all the required results (auth endpoint, public keys, signature algorithms, etc.). Using this function required to have set the property I_OPT_OPENID_CONFIG_ENDPOINT
.
The function i_build_auth_url_get
can be used to build the full auth request with all the parameters in the URL query for a GET request.
The function i_run_auth_request
builds the full auth requests and executes it. If the OAuth2 server answers with a successful response, the response will be parsed in the session properties. Otherwise, the redirect_to value and the errors if any will be parsed and made available in the session properties.
If the auth request is executed by an external program such as the browser, you can parse the redirect_to response afterwards using this function. You must set the I_OPT_REDIRECT_TO
.
If you need to run a device authorization request, you need to use the response type I_RESPONSE_TYPE_DEVICE_CODE
and use the function i_run_device_auth_request
, the parameter I_OPT_DEVICE_AUTHORIZATION_ENDPOINT
must be set. On success, the parameters I_OPT_DEVICE_AUTH_CODE
, I_OPT_DEVICE_AUTH_USER_CODE
, I_OPT_DEVICE_AUTH_VERIFICATION_URI
, I_OPT_DEVICE_AUTH_VERIFICATION_URI_COMPLETE
, I_OPT_DEVICE_AUTH_EXPIRES_IN
and I_OPT_DEVICE_AUTH_INTERVAL
will be set. After that, you'll need to run i_run_token_request
(see below) every few seconds until you get a success or a definitive error.
To run a device authorization request, you need to use the function i_run_par_request
, and the other parameters as if the request was a normal auth
request (response_type
, client_id
, scope
, redirect_uri
, authenticaiton type, etc.).
On success, the parameters I_OPT_PUSHED_AUTH_REQ_URI
and I_OPT_PUSHED_AUTH_REQ_EXPIRES_IN
will be automatically set. Then the function i_build_auth_url_get
will build an auth url using the request_uri and client_id parameters only.
To execute a request in the token endpoint, get a refresh token from a code or refresh a token,
Note: By default, token endpoint authentication method is I_TOKEN_AUTH_METHOD_NONE
. If your client needs to be authenticated, you must specify the desired method by setting the I_OPT_TOKEN_METHOD
with one of the following values:
I_TOKEN_AUTH_METHOD_SECRET_BASIC
: HTTP Basic AuthenticationI_TOKEN_AUTH_METHOD_SECRET_POST
: Secret Post AuthenticationI_TOKEN_AUTH_METHOD_TLS_CERTIFICATE
: MTLS authenticationI_TOKEN_AUTH_METHOD_JWT_SIGN_SECRET
: Client Assertion in JWT format signed with the client secretI_TOKEN_AUTH_METHOD_JWT_SIGN_PRIVKEY
: Client Assertion in JWT format signed with the client private keyI_TOKEN_AUTH_METHOD_JWT_ENCRYPT_SECRET
: Client Assertion in JWT format encrypted using the client secret or a client symmetric stored in the client_jwks
parameterI_TOKEN_AUTH_METHOD_JWT_ENCRYPT_PUBKEY
: Client Assertion in JWT format encrypted using the AS public keyThe values I_TOKEN_AUTH_METHOD_JWT_ENCRYPT_SECRET
and I_TOKEN_AUTH_METHOD_JWT_ENCRYPT_PUBKEY
must be combined with the values I_TOKEN_AUTH_METHOD_JWT_SIGN_SECRET
or I_TOKEN_AUTH_METHOD_JWT_SIGN_PRIVKEY
.
If the auth or token endpoints returns an id_token, this one will be parsed, the signature will be verified and the content will be validated to make sure the id_token is valid.
You can also manually validate an id_token using the dedicated function. The property I_OPT_ID_TOKEN
and the public key property must be set.
When an id_token is validated, its claims are available in the property json_t * struct _i_session.id_token_payload
.
If the access_token is a JWT, you can use the function i_verify_jwt_access_token
to verify its signature and content. The access token must use the format specified in the JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens standard.
The function will verify the claims iss
, iat
and aud
.
When an access_token is validated, its claims are available in the property json_t * struct _i_session.access_token_payload
.
If your Authorization Server provides JWT Access Tokens but not strictly according to the RFC, you can disable or enable the following JWT AT checks by (un)setting the following flags to the int property I_OPT_OPENID_CONFIG_STRICT
:
I_STRICT_JWT_AT_SIGNATURE
: verify JWT AT signatureI_STRICT_JWT_AT_HEADER_TYP
: verify JWT AT header typ to be 'jwt+at' or 'application/jwt+at'I_STRICT_JWT_AT_CLAIM
: verify mandatory other claims (iss, iat, etc.)If an access_token is available, you can make a request to the userinfo endpoint to get information about the user.
The function i_load_userinfo_custom
is a more advanced userinfo request where you can specify query or header parameters, to request more claims or the result as a signed JWT.
To execute introspection or revocation requests, you must set the session property I_OPT_TOKEN_TARGET
and I_OPT_TOKEN_TARGET_TYPE_HINT
if required.
You can register a new client using this dedicated functions.
You may have to set a I_OPT_ACCESS_TOKEN
property, depending on the server configuration. If update_session
is true and the registration is successful, the properties I_OPT_CLIENT_ID
and I_OPT_CLIENT_SECRET
will be set to the session, and the first redirect_to
entry will be used as I_OPT_REDIRECT_TO
value.
You can manage a client registration by changing its metadata or get the client registration metadata. These functions will use the access_token in the session if one is set.
You can use your client's private key parameters to generate a DPoP token. If you set the session property I_OPT_USE_DPOP
to true, the functions i_run_device_auth_request
, i_run_par_request
, i_get_userinfo_custom
, i_get_userinfo
, i_run_token_request
, i_revoke_token
, i_get_token_introspection
or i_perform_resource_service_request
will add a DPoP header.
If you are using Iddawc in a Resource Service (RS), you can check the DPoP sent by the client using the function i_verify_dpop_proof
. The parameter const char * access_token
is mandatory to comply with DPoP Definition, Draft 04.
When a request is sent to an Auth server or a Resource server, if the server can require a nonce in the DPoP to mitigate pre-generated DPoP tokens. If so, the server sends and error response with the status 400 for the AS and 401 for the RS, and the nonce required set int the HTTP response header "DPoP-Nonce"
. When the server sends such an error response, Iddawc will return a I_ERROR_PARAM
value when relevant, but will set the nonce in the struct _i_session
. It's up to the app using Iddawc to send another request by using the same function.
Example:
This features uses Ulfius' ulfius_send_http_request
function to proceed. This function requires at least a struct _u_request
with all the request parameters.
Iddawc will add the access token previously obtained to the HTTP request using the Bearer usage specified.
If the access token is expired, Iddawc will attempt to refresh the token.
If specified, Iddawc will generate and add a DPoP token in the request using the request parameters.
Here is an example of how to use i_perform_resource_service_request
:
Iddawc can run CIBA requests as defined in the documentation OpenID Connect Client-Initiated Backchannel Authentication Flow - Core 1.0.
Example of using i_run_ciba_request
:
Note that when using ping or push mode, Iddawc doesn't implement the client notification endpoint, its implementation and communication with iddawc's session will be yours to make.
Iddawc provides 3 functions dedicated to end session capabilities: OpenID Connect Front-Channel Logout and OpenID Connect Back-Channel Logout.
Even if Iddawc doesn't provide Front-Channel or Back-Channel logout endpoints, you can use the function i_verify_end_session_backchannel_token
to verify an end_session backchannel token, and i_close_session
to clean the current session.
Iddawc supports OAuth 2.0 Rich Authorization Requests Draft 11. You can manage RAR types using the following functions:
Then, when using the authentication functions (auth, device, ciba, par), the authorization_details
parameter will be set accordingly.