diff --git a/src/os_connect_client.eliomi b/src/os_connect_client.eliomi index c54bb0232..d12b232da 100644 --- a/src/os_connect_client.eliomi +++ b/src/os_connect_client.eliomi @@ -34,15 +34,17 @@ exception No_such_saved_token (** {2 Token representation. } *) -(** Represents tokens used by the OpenID Connect server. *) +(** Interface for ID Token used by the OpenID Connect server. *) -module type IDTOKEN = - sig - - (** Represents a saved token. The type is abstract to let the choice of the +module type IDTOKEN = sig + (** Represent a saved token. The type is abstract to let the choice of the implementation. In addition to {!Os_oauth2_client.TOKEN.saved_token}, a token must contain at least: + - the token type (for example ["bearer"]). + - the scopes list (of type {!scope}). Used to know which data the data + service must send. + - the ID token as a JSON Web Token (JWT). *) type saved_token @@ -61,27 +63,27 @@ module type IDTOKEN = (** [number_of_cycle] the number of cycle. *) val number_of_cycle : int - (** Returns the OpenID Connect server ID which delivered the token. *) + (** Return the OpenID Connect server ID which delivered the token. *) val id_server_of_saved_token : saved_token -> Os_types.OAuth2.Server.id - (** Returns the token value. *) + (** Return the token value. *) val value_of_saved_token : saved_token -> string - (** Returns the token type (for example ["bearer"]. *) + (** Return the token type (for example ["bearer"]. *) val token_type_of_saved_token : saved_token -> string - (** Returns the ID token as a JWT. *) + (** Return the ID token as a JWT. *) val id_token_of_saved_token : saved_token -> Jwt.t - (** Returns the number of remaining cycles. *) + (** Return the number of remaining cycles. *) val counter_of_saved_token : saved_token -> int ref @@ -116,7 +118,7 @@ module type IDTOKEN = saved_token -> unit - (** Returns all saved tokens as a list. *) + (** Return all saved tokens as a list. *) val list_tokens : unit -> saved_token list @@ -133,29 +135,28 @@ module type IDTOKEN = (** Basic scope for OpenID Connect. *) -module Basic_scope : - sig - (** Available scopes. When doing a request, [OpenID] is automatically - set. - *) - type scope = - | OpenID (** Mandatory in each requests (due to RFC).*) - | Firstname (** Get access to the first name *) - | Lastname (** Get access to the last name *) - | Email (** Get access to the email *) - | Unknown (** Used when an unknown scope is given. *) - - (** Default scopes is set to {{!scope}OpenID} (due to RFC). *) - val default_scopes : scope list - - (** Get a string representation of the scope. {{!scope}Unknown} string - representation is the empty string. - *) - val scope_to_str : scope -> string - - (** Converts a string scope to {!scope} type. *) - val scope_of_str : string -> scope - end +module Basic_scope : sig + (** Available scopes. When doing a request, [OpenID] is automatically + set. + *) + type scope = + | OpenID (** Mandatory in each requests (due to RFC).*) + | Firstname (** Get access to the first name *) + | Lastname (** Get access to the last name *) + | Email (** Get access to the email *) + | Unknown (** Used when an unknown scope is given. *) + + (** Default scopes is set to {{!scope}OpenID} (due to RFC). *) + val default_scopes : scope list + + (** Get a string representation of the scope. {{!scope}Unknown} string + representation is the empty string. + *) + val scope_to_str : scope -> string + + (** Converts a string scope to {!scope} type. *) + val scope_of_str : string -> scope +end (** Basic ID token implementation. *) diff --git a/src/os_connect_server.eliomi b/src/os_connect_server.eliomi index 14089ad67..a39a93c22 100644 --- a/src/os_connect_server.eliomi +++ b/src/os_connect_server.eliomi @@ -19,119 +19,192 @@ *) (** OpenID Connect server with default scopes ({!Basic_scope}), ID Tokens - ({!Basic_ID_Token}) and client implementation ({!Basic}). + ({!Basic_ID_Token}) and server implementation ({!Basic}). *) +(** {1 Exceptions. } *) + (** Exception raised when the given token doesn't exist. *) exception No_such_saved_token -module type IDTOKEN = - sig - type scope - - type saved_token - - val saved_tokens : saved_token list ref - - val cycle_duration : int - - val number_of_cycle : int - - val id_client_of_saved_token : - saved_token -> - Os_types.OAuth2.Client.id - - val userid_of_saved_token : - saved_token -> - Os_types.User.id - - val token_type_of_saved_token : - saved_token -> - string - - val value_of_saved_token : - saved_token -> - string - - val id_token_of_saved_token : - saved_token -> - Jwt.t - - val scope_of_saved_token : - saved_token -> - scope list - - val secret_key_of_saved_token : - saved_token -> - string - - val counter_of_saved_token : - saved_token -> - int ref - - (* getters *) - (* ------- *) - - (* Returns true if the token already exists *) - val token_exists : - saved_token -> - bool - - (* Generate a token value *) - val generate_token_value : - unit -> - string - - (* Generate a new token *) - val generate_token : - id_client:Os_types.OAuth2.Client.id -> - userid:Os_types.User.id -> - scope:scope list -> - saved_token Lwt.t - - (* Save a token *) - val save_token : - saved_token -> - unit - - val remove_saved_token : - saved_token -> - unit - - val saved_token_of_id_client_and_value : - Os_types.OAuth2.Server.id -> - string -> - saved_token - - (* List all saved tokens *) - val list_tokens : - unit -> - saved_token list - - val saved_token_to_json : - saved_token -> - Yojson.Safe.json - end +(** {2 Token representation. } *) + +(** Token interface used by the OpenID Connect server. *) + +module type IDTOKEN = sig + (** List of permissions. Used to type the [scope] field in {!saved_token} *) + type scope + + (** Token representation. The type is abstract to let the choice of the + implementation. + A token must contain at least: + - the userid to know which user authorized. + - the OAuth2.0 client ID to know the client to which the token is + assigned. The ID is related to the database. + - a value (the token value). + - the token type (for example ["bearer"]). + - the scopes list (of type {!scope}). Used to know which data the data + service must send. + - the ID token as a JSON Web Token (JWT). + - the secret key used to sign the JWT. It is useful to check if the + client sent the right ID token. This is the key used by HS256 to sign + the token. + - a counter which represents the number of times the token has been + checked by the timer. + *) + type saved_token + + (** The list of all saved tokens. *) + val saved_tokens : saved_token list ref + + (** Tokens must expire after a certain amount of time. For this reason, a + timer {!Os_oauth2_shared.update_list_timer} checks all {!cycle_duration} + seconds if the token has been generated after {!cycle_duration} * + {!number_of_cycle} seconds. If it's the case, the token is removed. + *) + + (** The duration of a cycle. *) + val cycle_duration : int + + (** The number of cycle. *) + val number_of_cycle : int + + (** Return the client ID. *) + val id_client_of_saved_token : + saved_token -> + Os_types.OAuth2.Client.id + + (** Return the userid of the user who authorized. *) + val userid_of_saved_token : + saved_token -> + Os_types.User.id + + (** Return the token type. *) + val token_type_of_saved_token : + saved_token -> + string + + (** Return the token value. *) + val value_of_saved_token : + saved_token -> + string + + (** Return the ID token as a JWT. *) + val id_token_of_saved_token : + saved_token -> + Jwt.t + + (** Return the scope asked by the client. *) + val scope_of_saved_token : + saved_token -> + scope list + + (** Return the secret key used to sign the JWT. *) + val secret_key_of_saved_token : + saved_token -> + string + + (** Return the number of passed cycle. *) + val counter_of_saved_token : + saved_token -> + int ref + + (** Return [true] if the token already exists *) + val token_exists : + saved_token -> + bool + + (* Generate a token value *) + val generate_token_value : + unit -> + string + + (* Generate a new token *) + val generate_token : + id_client:Os_types.OAuth2.Client.id -> + userid:Os_types.User.id -> + scope:scope list -> + saved_token Lwt.t + + (** Save a token *) + val save_token : + saved_token -> + unit + + (** Remove a token. *) + val remove_saved_token : + saved_token -> + unit + + (** Return the saved token assigned to the client with given ID and + value. + *) + val saved_token_of_id_client_and_value : + Os_types.OAuth2.Server.id -> + string -> + saved_token + + (* List all saved tokens *) + val list_tokens : + unit -> + saved_token list + + (** Return the saved token as a JSON. Used to send to the client. *) + val saved_token_to_json : + saved_token -> + Yojson.Safe.json +end (** Basic module for scopes. + [check_scope_list scope_list] returns [true] if every element in [scope_list] is an available scope value. If the list contains only [OpenID] or if the list doesn't contain [OpenID] - (mandatory scope in RFC), returns [false]. + (mandatory scope in RFC), it returns [false]. If an unknown scope value is in list (represented by [Unknown] value), - returns [false]. + it returns [false]. *) +(** Basic scope *) module Basic_scope : Os_oauth2_server.SCOPE +(** MakeIDToken (Scope) returns a module of type {!IDTOKEN} with the type + {!IDTOKEN.scope} equals to {!Scope.scope}. + + Tokens are represented as a record with exactly the same fields available in + the inferface {!IDTOKEN}. + + The token type is always ["bearer"]. + + The related JSON contains the fields: + - ["token_type"] with value ["bearer"]. + - ["token"] with the token value. + - ["expires_in"] with the value [cycle_duration * number_of_cycle] i.e. 600 + seconds. + - ["id_token"] with the JWT. + + + NOTE: If you want to implement another type of tokens, you need to implement + another functor (with the [Scope.scope] type dependency) which returns a + module of type {!IDTOKEN}. The resulting module can be given as parameter to + the function {!Os_oauth2_server.MakeServer}. + *) module MakeIDToken : functor (Scope : Os_oauth2_server.SCOPE) -> (IDTOKEN with type scope = Scope.scope) +(** Basic ID Token based on the scope from {!Basic_scope}. *) module Basic_ID_token : (IDTOKEN with type scope = Basic_scope.scope) +(** [Basic (Scope) (Token)] returns a module representing a OpenID Connect + server. The available scopes come from {!Scope.scope} and the token related + functions, types and representation come from {!Token}. + + As an OpenID Connect server is based on an OAuth2.0, the server is generated + with {!Os_oauth2_server.MakeServer}. + *) module Basic : (Os_oauth2_server.SERVER with type scope = Basic_scope.scope and type saved_token = Basic_ID_token.saved_token diff --git a/src/os_oauth2_client.eliomi b/src/os_oauth2_client.eliomi index 0efe459f5..fb553292a 100644 --- a/src/os_oauth2_client.eliomi +++ b/src/os_oauth2_client.eliomi @@ -185,22 +185,22 @@ module type TOKEN = sig (** [number_of_cycle] is the number of cycle. *) val number_of_cycle : int - (** Returns the OpenID Connect server ID which delivered the token. *) + (** Return the OpenID Connect server ID which delivered the token. *) val id_server_of_saved_token : saved_token -> Os_types.OAuth2.Server.id - (** Returns the token value. *) + (** Return the token value. *) val value_of_saved_token : saved_token -> string - (** Returns the token type (for example ["bearer"]). *) + (** Return the token type (for example ["bearer"]). *) val token_type_of_saved_token : saved_token -> string - (** Returns the number of passed cycles. *) + (** Return the number of passed cycles. *) val counter_of_saved_token : saved_token -> int ref @@ -235,7 +235,7 @@ module type TOKEN = sig saved_token -> unit - (** Returns all saved tokens as a list. *) + (** Return all saved tokens as a list. *) val list_tokens : unit -> saved_token list @@ -378,7 +378,7 @@ module Basic_scope : sig end (** Basic_token is a {!TOKEN} module representing a basic token (id_server, - value and token_type. + value and token_type). This token representation is used in {!Os_oauth2_server.Basic} so you can to use this module if the OAuth2 server is an instance of {!Os_oauth2_server.Basic}. diff --git a/src/os_oauth2_server.eliomi b/src/os_oauth2_server.eliomi index c4d9c7c16..320bc5bb0 100644 --- a/src/os_oauth2_server.eliomi +++ b/src/os_oauth2_server.eliomi @@ -146,142 +146,141 @@ val list_clients : (** {2 Scopes, tokens and basic implementations of them. } *) (** Interface for scopes. *) -module type SCOPE = - sig - (** Scope is a list of permissions. *) - type scope - - val scope_of_str : - string -> - scope - - val scope_to_str : - scope -> - string - - (** Return [true] if the scope asked by the client is - allowed, else [false]. - - You can implement simple check functions by only checking if all - elements of the scopes list are defined but you can also have the case - where two scopes can't be asked at the same time. - *) - val check_scope_list : - scope list -> - bool - end +module type SCOPE = sig + (** Scope is a list of permissions. *) + type scope + + val scope_of_str : + string -> + scope + + val scope_to_str : + scope -> + string + + (** Return [true] if the scope asked by the client is + allowed, else [false]. + + You can implement simple check functions by only checking if all + elements of the scopes list are defined but you can also have the case + where two scopes can't be asked at the same time. + *) + val check_scope_list : + scope list -> + bool +end (** Interface for tokens. *) -module type TOKEN = - sig - (** List of permissions. Used to type the [scope] field in {!saved_token} *) - type scope - (** Saved token representation. The type is abstract to let the choice of - the implementation. - A token must contain at least: - - the userid to know which user authorized. - - the OAuth2.0 client ID to know the client to which the token is - assigned. The ID is related to the database. - - a value (the token value). - - the token type (for example ["bearer"]). - - the scopes list (of type {!scope}). Used to know which data the data - service must send. - - a counter which represents the number of times the token has been - checked by the timer. - *) - type saved_token - - (** The list of all saved tokens. *) - val saved_tokens : saved_token list ref - - (** Tokens must expire after a certain amount of time. For this reason, a - timer {!Os_oauth2_shared.update_list_timer} checks all {!cycle_duration} - seconds if the token has been generated after {!cycle_duration} * - {!number_of_cycle} seconds. If it's the case, the token is removed. - *) - - (** The duration of a cycle. *) - val cycle_duration : int - - (** The number of cycle. *) - val number_of_cycle : int - - (** Return the client ID. *) - val id_client_of_saved_token : - saved_token -> - Os_types.OAuth2.Client.id - - (** Return the userid of the user who authorized. *) - val userid_of_saved_token : - saved_token -> - Os_types.User.id - - (** Return the token value. *) - val value_of_saved_token : - saved_token -> - string - - (** Return the token type. *) - val token_type_of_saved_token : - saved_token -> - string - - (** Return the scope asked by the client. *) - val scope_of_saved_token : - saved_token -> - scope list - - (** Return the number of passed cycle. *) - val counter_of_saved_token : - saved_token -> - int ref - - (** Return [true] if the token already exists. *) - val token_exists : - saved_token -> - bool - - (** Generate a token value. *) - val generate_token_value : - unit -> - string - - (** Generate a new token. *) - val generate_token : - id_client:Os_types.OAuth2.Client.id -> - userid:Os_types.User.id -> - scope:scope list -> - saved_token Lwt.t - - (** Save a token. *) - val save_token : - saved_token -> - unit - - (** Remove a saved token. *) - val remove_saved_token : - saved_token -> - unit - - (** Return the saved token assigned to the client with given ID and - value. - *) - val saved_token_of_id_client_and_value : - Os_types.OAuth2.Client.id -> - string -> - saved_token - - (** List all saved tokens *) - val list_tokens : - unit -> - saved_token list - - (** Return the saved token as a JSON. Used to send to the client. *) - val saved_token_to_json : - saved_token -> - Yojson.Safe.json - end +module type TOKEN = sig + (** List of permissions. Used to type the [scope] field in {!saved_token} *) + type scope + + (** Saved token representation. The type is abstract to let the choice of + the implementation. + A token must contain at least: + - the userid to know which user authorized. + - the OAuth2.0 client ID to know the client to which the token is + assigned. The ID is related to the database. + - a value (the token value). + - the token type (for example ["bearer"]). + - the scopes list (of type {!scope}). Used to know which data the data + service must send. + - a counter which represents the number of times the token has been + checked by the timer. + *) + type saved_token + + (** The list of all saved tokens. *) + val saved_tokens : saved_token list ref + + (** Tokens must expire after a certain amount of time. For this reason, a + timer {!Os_oauth2_shared.update_list_timer} checks all {!cycle_duration} + seconds if the token has been generated after {!cycle_duration} * + {!number_of_cycle} seconds. If it's the case, the token is removed. + *) + + (** The duration of a cycle. *) + val cycle_duration : int + + (** The number of cycle. *) + val number_of_cycle : int + + (** Return the client ID. *) + val id_client_of_saved_token : + saved_token -> + Os_types.OAuth2.Client.id + + (** Return the userid of the user who authorized. *) + val userid_of_saved_token : + saved_token -> + Os_types.User.id + + (** Return the token value. *) + val value_of_saved_token : + saved_token -> + string + + (** Return the token type. *) + val token_type_of_saved_token : + saved_token -> + string + + (** Return the scope asked by the client. *) + val scope_of_saved_token : + saved_token -> + scope list + + (** Return the number of passed cycle. *) + val counter_of_saved_token : + saved_token -> + int ref + + (** Return [true] if the token already exists. *) + val token_exists : + saved_token -> + bool + + (** Generate a token value. *) + val generate_token_value : + unit -> + string + + (** Generate a new token. *) + val generate_token : + id_client:Os_types.OAuth2.Client.id -> + userid:Os_types.User.id -> + scope:scope list -> + saved_token Lwt.t + + (** Save a token. *) + val save_token : + saved_token -> + unit + + (** Remove a saved token. *) + val remove_saved_token : + saved_token -> + unit + + (** Return the saved token assigned to the client with given ID and + value. + *) + val saved_token_of_id_client_and_value : + Os_types.OAuth2.Client.id -> + string -> + saved_token + + (** List all saved tokens *) + val list_tokens : + unit -> + saved_token list + + (** Return the saved token as a JSON. Used to send to the client. *) + val saved_token_to_json : + saved_token -> + Yojson.Safe.json +end (** Interface for OAuth2.0 servers. See also {!MakeServer}.