Iddawc: Iddawc API documentation

Iddawc Handle the flow of OAuth2 and OpenID Connect authentication process from the client side.

Iddawc API documentation

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:

- Loading openid-configuration endpoints and parsing the results
- Making `auth` requests using the given parameters (`client_id`, `client_secret`, `redirect_uri`, etc.) and parsing the result
- Making `token` requests using the given parameters (`code`, `client_id`, `client_secret`, `redirect_uri`, etc.) and parsing the result
- Making `userinfo`, `token introspection`, `token revocation` requests
- Parse responses, validate id_token
- Registering new clients using the `register` endpoint if any
- Sending signed and or encrypted requests in the `auth` and `token` endpoints
- Client TLS Authentication available
- Making Pushed Auth Requests
- Making Rich Auth Requests
- Adding claims to requests
- Sending DPoP proofs
- JWT Secured Authorization Response Mode
- End session and single-logout functionalities

# Return values

Lots of functions in Rhonabwy library return an int value. The returned value can be one of the following:

#define I_OK 0
#define I_ERROR 1
#define I_ERROR_PARAM 2
#define I_ERROR_MEMORY 3
#define I_ERROR_UNAUTHORIZED 4
#define I_ERROR_SERVER 5

If a function is successful, it will return `I_OK` (0), otherwise an error code is returned.

# Global init and close

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.

int i_global_init();
void i_global_close();
i_global_init
int i_global_init()
Definition: iddawc.c:1417
i_global_close
void i_global_close()
Definition: iddawc.c:1426

# Log messages

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:

int main() {
y_init_logs("Iddawc", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG, NULL, "Starting Iddawc client program");
// Do your code here
y_close_logs();
}

Example of an error log message:

2020-04-05T16:14:31 - Iddawc: i_run_auth_request - Unsupported auth_method

Go to Yder API Documentation for more details.

# Core functions and struct _i_session * variables

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.

int i_init_session(struct _i_session * i_session);
void i_clean_session(struct _i_session * i_session);
i_init_session
int i_init_session(struct _i_session *i_session)
Definition: iddawc.c:1435
i_clean_session
void i_clean_session(struct _i_session *i_session)
Definition: iddawc.c:1587
_i_session
Definition: iddawc.h:267

## Get or set properties

To set or get parameters stored in the `struct _i_session *`, you must use the appropriate function

int i_set_response_type(struct _i_session * i_session, uint i_value);
int i_set_result(struct _i_session * i_session, uint i_value);
int i_set_int_parameter(struct _i_session * i_session, i_option option, uint i_value);
int i_set_str_parameter(struct _i_session * i_session, i_option option, const char * s_value);
int i_set_additional_parameter(struct _i_session * i_session, const char * s_key, const char * s_value);
int i_set_additional_response(struct _i_session * i_session, const char * s_key, const char * s_value);
uint i_get_response_type(struct _i_session * i_session);
uint i_get_result(struct _i_session * i_session);
uint i_get_int_parameter(struct _i_session * i_session, i_option option);
const char * i_get_str_parameter(struct _i_session * i_session, i_option option);
const char * i_get_additional_parameter(struct _i_session * i_session, const char * s_key);
const char * i_get_additional_response(struct _i_session * i_session, const char * s_key);
int i_set_rich_authorization_request(struct _i_session * i_session, const char * type, const char * value);
int i_remove_rich_authorization_request(struct _i_session * i_session, const char * type);
char * i_get_rich_authorization_request(struct _i_session * i_session, const char * type);
int i_set_parameter_list(struct _i_session * i_session, ...);
i_option
i_option
Definition: iddawc.h:135
i_get_str_parameter
const char * i_get_str_parameter(struct _i_session *i_session, i_option option)
Definition: iddawc.c:3156
i_get_int_parameter
uint i_get_int_parameter(struct _i_session *i_session, i_option option)
Definition: iddawc.c:2989
i_get_result
uint i_get_result(struct _i_session *i_session)
Definition: iddawc.c:2985
i_set_additional_parameter
int i_set_additional_parameter(struct _i_session *i_session, const char *s_key, const char *s_value)
Definition: iddawc.c:2551
i_set_int_parameter
int i_set_int_parameter(struct _i_session *i_session, i_option option, uint i_value)
Definition: iddawc.c:1667
i_set_result
int i_set_result(struct _i_session *i_session, uint i_value)
Definition: iddawc.c:1663
i_set_parameter_list
int i_set_parameter_list(struct _i_session *i_session,...)
Definition: iddawc.c:2651
i_remove_rich_authorization_request
int i_remove_rich_authorization_request(struct _i_session *i_session, const char *type)
Definition: iddawc.c:5914
i_get_response_type
uint i_get_response_type(struct _i_session *i_session)
Definition: iddawc.c:2981
i_get_additional_parameter
const char * i_get_additional_parameter(struct _i_session *i_session, const char *s_key)
Definition: iddawc.c:3420
i_set_response_type
int i_set_response_type(struct _i_session *i_session, uint i_value)
Definition: iddawc.c:1659
i_set_str_parameter
int i_set_str_parameter(struct _i_session *i_session, i_option option, const char *s_value)
Definition: iddawc.c:1854
i_get_additional_response
const char * i_get_additional_response(struct _i_session *i_session, const char *s_key)
Definition: iddawc.c:3428
i_set_additional_response
int i_set_additional_response(struct _i_session *i_session, const char *s_key, const char *s_value)
Definition: iddawc.c:2563

## Import or export sessions

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.

json_t * i_export_session_json_t(struct _i_session * i_session);
int i_import_session_json_t(struct _i_session * i_session, json_t * j_import);
char * i_export_session_str(struct _i_session * i_session);
int i_import_session_str(struct _i_session * i_session, const char * str_import);
i_export_session_json_t
json_t * i_export_session_json_t(struct _i_session *i_session)
Definition: iddawc.c:5191
i_import_session_json_t
int i_import_session_json_t(struct _i_session *i_session, json_t *j_import)
Definition: iddawc.c:5345
i_import_session_str
int i_import_session_str(struct _i_session *i_session, const char *str_import)
Definition: iddawc.c:5521
i_export_session_str
char * i_export_session_str(struct _i_session *i_session)
Definition: iddawc.c:5510

# Run OAuth2 or OIDC requests

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.

## Load openid-config

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`.

int i_get_openid_config(struct _i_session * i_session);
i_get_openid_config
int i_get_openid_config(struct _i_session *i_session)
Definition: iddawc.c:2806

## Build and run auth request and parse results

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.

int i_build_auth_url_get(struct _i_session * i_session);
i_build_auth_url_get
int i_build_auth_url_get(struct _i_session *i_session)
Definition: iddawc.c:3490

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.

int i_run_auth_request(struct _i_session * i_session);
i_run_auth_request
int i_run_auth_request(struct _i_session *i_session)
Definition: iddawc.c:3654

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`.

int i_parse_redirect_to(struct _i_session * i_session);
i_parse_redirect_to
int i_parse_redirect_to(struct _i_session *i_session)
Definition: iddawc.c:3075

## Build and run device authorization requests and parse results

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.

int i_run_device_auth_request(struct _i_session * i_session);
i_run_device_auth_request
int i_run_device_auth_request(struct _i_session *i_session)
Definition: iddawc.c:5963

## Build and run pushed authorization requests and parse results

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.

int i_run_par_request(struct _i_session * i_session);
i_run_par_request
int i_run_par_request(struct _i_session *i_session)
Definition: iddawc.c:6064

## Build and run token requests and parse results

To execute a request in the token endpoint, get a refresh token from a code or refresh a token,

int i_run_token_request(struct _i_session * i_session);
i_run_token_request
int i_run_token_request(struct _i_session *i_session)
Definition: iddawc.c:3886

## Verify an id_token

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`.

int i_verify_id_token(struct _i_session * i_session);
i_verify_id_token
int i_verify_id_token(struct _i_session *i_session)
Definition: iddawc.c:4317

## Verify an access_token

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`.

int i_verify_jwt_access_token(struct _i_session * i_session, const char * aud);
i_verify_jwt_access_token
int i_verify_jwt_access_token(struct _i_session *i_session, const char *aud)
Definition: iddawc.c:4476

## Load userinfo

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.

int i_get_userinfo(struct _i_session * i_session, int get_jwt);
int i_get_userinfo_custom(struct _i_session * i_session, const char * http_method, struct _u_map * additional_query, struct _u_map * additional_headers);
i_get_userinfo_custom
int i_get_userinfo_custom(struct _i_session *i_session, const char *http_method, struct _u_map *additional_query, struct _u_map *additional_headers)
Definition: iddawc.c:2867
i_get_userinfo
int i_get_userinfo(struct _i_session *i_session, int get_jwt)
Definition: iddawc.c:2850

## Introspect or revoke tokens

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.

int i_introspect_token(struct _i_session * i_session, json_t ** j_result);
int i_revoke_token(struct _i_session * i_session);
i_revoke_token
int i_revoke_token(struct _i_session *i_session, int authentication)
Definition: iddawc.c:4518

## Register new clients

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.

int i_register_client(struct _i_session * i_session, json_t * j_parameters, int update_session, json_t ** j_result);
i_register_client
int i_register_client(struct _i_session *i_session, json_t *j_parameters, int update_session, json_t **j_result)
Definition: iddawc.c:4776

## Manage clients registration

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.

int i_manage_registration_client(struct _i_session * i_session, json_t * j_parameters, int update_session, json_t ** j_result);
int i_get_registration_client(struct _i_session * i_session, json_t ** j_result);
i_get_registration_client
int i_get_registration_client(struct _i_session *i_session, json_t **j_result)
Definition: iddawc.c:4952
i_manage_registration_client
int i_manage_registration_client(struct _i_session *i_session, json_t *j_parameters, int update_session, json_t **j_result)
Definition: iddawc.c:5021

## Generate a DPoP token

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.

char * i_generate_dpop_token(struct _i_session * i_session, const char * htm, const char * htu, time_t iat, int add_ath);
i_generate_dpop_token
char * i_generate_dpop_token(struct _i_session *i_session, const char *htm, const char *htu, time_t iat, int add_ath)
Definition: iddawc.c:5539

## Verify a DPoP proof

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.

int i_verify_dpop_proof(const char * dpop_header, const char * htm, const char * htu, time_t max_iat, const char * jkt, const char * access_token);
i_verify_dpop_proof
int i_verify_dpop_proof(const char *dpop_header, const char *htm, const char *htu, time_t max_iat, const char *jkt, const char *access_token)
Definition: iddawc.c:5741

## Perform a HTTP request to a Resource Service

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.

int i_perform_resource_service_request(struct _i_session * i_session, struct _u_request * http_request, struct _u_response * http_response, int refresh_if_expired, int bearer_type, int use_dpop, time_t dpop_iat);
i_perform_resource_service_request
int i_perform_resource_service_request(struct _i_session *i_session, struct _u_request *http_request, struct _u_response *http_response, int refresh_if_expired, int bearer_type, int use_dpop, time_t dpop_iat)
Definition: iddawc.c:5650

Here is an example of how to use `i_perform_resource_service_request`:

struct _i_session i_session;
struct _u_request req;
struct _u_response resp;
json_t * j_resp;
i_init_session(&i_session);
/*
* All the process to get an access token is hidden, this example considers the _i_session has an access token
*/
ulfius_init_request(&req);
ulfius_init_response(&resp);
ulfius_set_request_properties(&req, U_OPT_HTTP_VERB, "GET", U_OPT_HTTP_URL, "https://resource.tld/object", U_OPT_NONE);
if (i_perform_resource_service_request(&i_session, &req, &resp, 1, I_BEARER_TYPE_HEADER, 1) == I_OK && resp.status == 200) {
// j_resp contains the JSON response of the protected resource
j_resp = ulfius_get_json_body_response(&resp, NULL);
}
i_clean_session(&i_session);
ulfius_clean_request(&req);
ulfius_clean_response(&resp);
json_decref(j_resp);
I_BEARER_TYPE_HEADER
#define I_BEARER_TYPE_HEADER
Bearer type header, the token will be available in the header.
Definition: iddawc.h:82
I_OK
#define I_OK
Success.
Definition: iddawc.h:44

## CIBA Requests

Iddawc can run CIBA requests as defined in the documentation OpenID Connect Client-Initiated Backchannel Authentication Flow - Core 1.0.

int i_run_ciba_request(struct _i_session * i_session);
i_run_ciba_request
int i_run_ciba_request(struct _i_session *i_session)
Definition: iddawc.c:6189

Example of using `i_run_ciba_request`:

struct _i_session i_session;
i_init_session(&i_session);
i_set_parameter_list(&i_session, I_OPT_RESPONSE_TYPE, I_RESPONSE_TYPE_CIBA,
I_OPT_OPENID_CONFIG_ENDPOINT, "https://as.tld/.well-known/openid-configuration",
I_OPT_CLIENT_ID, "client",
I_OPT_CLIENT_SECRET, "secret",
I_OPT_AUTH_METHOD, I_TOKEN_AUTH_METHOD_SECRET_BASIC,
I_OPT_SCOPE, "openid",
I_OPT_CIBA_LOGIN_HINT, "{\"username\":\"ciba\"}",
I_OPT_CIBA_MODE, I_CIBA_MODE_POLL,
I_OPT_CIBA_LOGIN_HINT_FORMAT, I_CIBA_LOGIN_HINT_FORMAT_JSON,
I_OPT_NONE);
i_get_openid_config(&i_session); // get CIBA endpoint
i_run_ciba_request(&i_session); // run request and store auth_req_id
i_run_token_request(&i_session); // get access_token and refresh_token when the user has completed the authentication
I_CIBA_MODE_POLL
#define I_CIBA_MODE_POLL
Definition: iddawc.h:122
I_RESPONSE_TYPE_CIBA
#define I_RESPONSE_TYPE_CIBA
Grant type urn:openid:params:grant-type:ciba.
Definition: iddawc.h:59
I_CIBA_LOGIN_HINT_FORMAT_JSON
#define I_CIBA_LOGIN_HINT_FORMAT_JSON
Definition: iddawc.h:126
I_TOKEN_AUTH_METHOD_SECRET_BASIC
#define I_TOKEN_AUTH_METHOD_SECRET_BASIC
token endpoint using HTTP basic auth with client_id and client password
Definition: iddawc.h:69
I_OPT_CIBA_LOGIN_HINT
@ I_OPT_CIBA_LOGIN_HINT
CIBA login_hint value, mandatory on CIBA requests.
Definition: iddawc.h:239
I_OPT_CIBA_LOGIN_HINT_FORMAT
@ I_OPT_CIBA_LOGIN_HINT_FORMAT
CIBA login_hint format, values available are I_CIBA_LOGIN_HINT_FORMAT_JSON, I_CIBA_LOGIN_HINT_FORMAT_...
Definition: iddawc.h:240
I_OPT_OPENID_CONFIG_ENDPOINT
@ I_OPT_OPENID_CONFIG_ENDPOINT
absolute url for the .well-known/openid-configuration endpoint, string
Definition: iddawc.h:150
I_OPT_NONE
@ I_OPT_NONE
Empty option to complete a i_set_parameter_list.
Definition: iddawc.h:136
I_OPT_CIBA_MODE
@ I_OPT_CIBA_MODE
backchannel token delivery mode, values available are I_CIBA_MODE_NONE, I_CIBA_MODE_POLL,...
Definition: iddawc.h:237
I_OPT_CLIENT_SECRET
@ I_OPT_CLIENT_SECRET
client secret, string
Definition: iddawc.h:145
I_OPT_CLIENT_ID
@ I_OPT_CLIENT_ID
client_id, string
Definition: iddawc.h:144
I_OPT_RESPONSE_TYPE
@ I_OPT_RESPONSE_TYPE
response_type, values available are I_RESPONSE_TYPE_CODE, I_RESPONSE_TYPE_TOKEN, I_RESPONSE_TYPE_ID_T...
Definition: iddawc.h:137
I_OPT_AUTH_METHOD
@ I_OPT_AUTH_METHOD
Authentication method to use with the auth endpoint, values available are I_AUTH_METHOD_GET,...
Definition: iddawc.h:162
I_OPT_SCOPE
@ I_OPT_SCOPE
scope values, string, multiple scopes must be separated by a space character: "scope1 openid"
Definition: iddawc.h:138

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.

## End session

Iddawc provides 3 functions dedicated to end session capabilities: OpenID Connect Front-Channel Logout and OpenID Connect Back-Channel Logout.

char * i_build_end_session_url(struct _i_session * i_session);
int i_verify_end_session_backchannel_token(struct _i_session * i_session, const char * token);
int i_close_session(struct _i_session * i_session, const char * sid);
i_verify_end_session_backchannel_token
int i_verify_end_session_backchannel_token(struct _i_session *i_session, const char *token)
Definition: iddawc.c:6429
i_build_end_session_url
char * i_build_end_session_url(struct _i_session *i_session)
Definition: iddawc.c:6414
i_close_session
int i_close_session(struct _i_session *i_session, const char *sid)
Definition: iddawc.c:6480

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.