Skip to content

Commit

Permalink
Update documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
dannywillems committed Nov 3, 2016
1 parent f3937eb commit 23a6864
Show file tree
Hide file tree
Showing 4 changed files with 336 additions and 263 deletions.
69 changes: 35 additions & 34 deletions src/os_connect_client.eliomi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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. *)

Expand Down
253 changes: 163 additions & 90 deletions src/os_connect_server.eliomi
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 23a6864

Please sign in to comment.