|  | 
| 19 | 19 |  *) | 
| 20 | 20 | 
 | 
| 21 | 21 | (** OpenID Connect server with default scopes ({!Basic_scope}), ID Tokens | 
| 22 |  | -    ({!Basic_ID_Token}) and client implementation ({!Basic}). | 
|  | 22 | +    ({!Basic_ID_Token}) and server implementation ({!Basic}). | 
| 23 | 23 |  *) | 
| 24 | 24 | 
 | 
|  | 25 | +(** {1 Exceptions. } *) | 
|  | 26 | + | 
| 25 | 27 | (** Exception raised when the given token doesn't exist. *) | 
| 26 | 28 | exception No_such_saved_token | 
| 27 | 29 | 
 | 
| 28 |  | -module type IDTOKEN = | 
| 29 |  | -  sig | 
| 30 |  | -    type scope | 
| 31 |  | - | 
| 32 |  | -    type saved_token | 
| 33 |  | - | 
| 34 |  | -    val saved_tokens : saved_token list ref | 
| 35 |  | - | 
| 36 |  | -    val cycle_duration  : int | 
| 37 |  | - | 
| 38 |  | -    val number_of_cycle : int | 
| 39 |  | - | 
| 40 |  | -    val id_client_of_saved_token : | 
| 41 |  | -      saved_token -> | 
| 42 |  | -      Os_types.OAuth2.Client.id | 
| 43 |  | - | 
| 44 |  | -    val userid_of_saved_token : | 
| 45 |  | -      saved_token -> | 
| 46 |  | -      Os_types.User.id | 
| 47 |  | - | 
| 48 |  | -    val token_type_of_saved_token : | 
| 49 |  | -      saved_token -> | 
| 50 |  | -      string | 
| 51 |  | - | 
| 52 |  | -    val value_of_saved_token : | 
| 53 |  | -      saved_token -> | 
| 54 |  | -      string | 
| 55 |  | - | 
| 56 |  | -    val id_token_of_saved_token : | 
| 57 |  | -      saved_token -> | 
| 58 |  | -      Jwt.t | 
| 59 |  | - | 
| 60 |  | -    val scope_of_saved_token : | 
| 61 |  | -      saved_token -> | 
| 62 |  | -      scope list | 
| 63 |  | - | 
| 64 |  | -    val secret_key_of_saved_token : | 
| 65 |  | -      saved_token -> | 
| 66 |  | -      string | 
| 67 |  | - | 
| 68 |  | -    val counter_of_saved_token    : | 
| 69 |  | -      saved_token -> | 
| 70 |  | -      int ref | 
| 71 |  | - | 
| 72 |  | -    (* getters *) | 
| 73 |  | -    (* ------- *) | 
| 74 |  | - | 
| 75 |  | -    (* Returns true if the token already exists *) | 
| 76 |  | -    val token_exists              : | 
| 77 |  | -      saved_token                 -> | 
| 78 |  | -      bool | 
| 79 |  | - | 
| 80 |  | -    (* Generate a token value *) | 
| 81 |  | -    val generate_token_value      : | 
| 82 |  | -      unit                        -> | 
| 83 |  | -      string | 
| 84 |  | - | 
| 85 |  | -    (* Generate a new token *) | 
| 86 |  | -    val generate_token            : | 
| 87 |  | -      id_client:Os_types.OAuth2.Client.id -> | 
| 88 |  | -      userid:Os_types.User.id             -> | 
| 89 |  | -      scope:scope list                    -> | 
| 90 |  | -      saved_token Lwt.t | 
| 91 |  | - | 
| 92 |  | -    (* Save a token *) | 
| 93 |  | -    val save_token                : | 
| 94 |  | -      saved_token                 -> | 
| 95 |  | -      unit | 
| 96 |  | - | 
| 97 |  | -    val remove_saved_token        : | 
| 98 |  | -      saved_token                 -> | 
| 99 |  | -      unit | 
| 100 |  | - | 
| 101 |  | -    val saved_token_of_id_client_and_value : | 
| 102 |  | -      Os_types.OAuth2.Server.id -> | 
| 103 |  | -      string                    -> | 
| 104 |  | -      saved_token | 
| 105 |  | - | 
| 106 |  | -    (* List all saved tokens *) | 
| 107 |  | -    val list_tokens               : | 
| 108 |  | -      unit                        -> | 
| 109 |  | -      saved_token list | 
| 110 |  | - | 
| 111 |  | -    val saved_token_to_json       : | 
| 112 |  | -      saved_token                 -> | 
| 113 |  | -      Yojson.Safe.json | 
| 114 |  | -  end | 
|  | 30 | +(** {2 Token representation. } *) | 
|  | 31 | + | 
|  | 32 | +(** Token interface used by the OpenID Connect server. *) | 
|  | 33 | + | 
|  | 34 | +module type IDTOKEN = sig | 
|  | 35 | +  (** List of permissions. Used to type the [scope] field in {!saved_token} *) | 
|  | 36 | +  type scope | 
|  | 37 | + | 
|  | 38 | +  (** Token representation. The type is abstract to let the choice of the | 
|  | 39 | +      implementation. | 
|  | 40 | +      A token must contain at least: | 
|  | 41 | +      - the userid to know which user authorized. | 
|  | 42 | +      - the OAuth2.0 client ID to know the client to which the token is | 
|  | 43 | +        assigned. The ID is related to the database. | 
|  | 44 | +      - a value (the token value). | 
|  | 45 | +      - the token type (for example ["bearer"]). | 
|  | 46 | +      - the scopes list (of type {!scope}). Used to know which data the data | 
|  | 47 | +      service must send. | 
|  | 48 | +      - the ID token as a JSON Web Token (JWT). | 
|  | 49 | +      - the secret key used to sign the JWT. It is useful to check if the | 
|  | 50 | +      client sent the right ID token. This is the key used by HS256 to sign | 
|  | 51 | +      the token. | 
|  | 52 | +      - a counter which represents the number of times the token has been | 
|  | 53 | +        checked by the timer. | 
|  | 54 | +   *) | 
|  | 55 | +  type saved_token | 
|  | 56 | + | 
|  | 57 | +  (** The list of all saved tokens. *) | 
|  | 58 | +  val saved_tokens : saved_token list ref | 
|  | 59 | + | 
|  | 60 | +  (** Tokens must expire after a certain amount of time. For this reason, a | 
|  | 61 | +      timer {!Os_oauth2_shared.update_list_timer} checks all {!cycle_duration} | 
|  | 62 | +      seconds if the token has been generated after {!cycle_duration} * | 
|  | 63 | +      {!number_of_cycle} seconds. If it's the case, the token is removed. | 
|  | 64 | +   *) | 
|  | 65 | + | 
|  | 66 | +  (** The duration of a cycle. *) | 
|  | 67 | +  val cycle_duration  : int | 
|  | 68 | + | 
|  | 69 | +  (** The number of cycle. *) | 
|  | 70 | +  val number_of_cycle : int | 
|  | 71 | + | 
|  | 72 | +  (** Return the client ID. *) | 
|  | 73 | +  val id_client_of_saved_token : | 
|  | 74 | +    saved_token -> | 
|  | 75 | +    Os_types.OAuth2.Client.id | 
|  | 76 | + | 
|  | 77 | +  (** Return the userid of the user who authorized. *) | 
|  | 78 | +  val userid_of_saved_token : | 
|  | 79 | +    saved_token -> | 
|  | 80 | +    Os_types.User.id | 
|  | 81 | + | 
|  | 82 | +  (** Return the token type. *) | 
|  | 83 | +  val token_type_of_saved_token : | 
|  | 84 | +    saved_token -> | 
|  | 85 | +    string | 
|  | 86 | + | 
|  | 87 | +  (** Return the token value. *) | 
|  | 88 | +  val value_of_saved_token : | 
|  | 89 | +    saved_token -> | 
|  | 90 | +    string | 
|  | 91 | + | 
|  | 92 | +  (** Return the ID token as a JWT. *) | 
|  | 93 | +  val id_token_of_saved_token : | 
|  | 94 | +    saved_token -> | 
|  | 95 | +    Jwt.t | 
|  | 96 | + | 
|  | 97 | +  (** Return the scope asked by the client. *) | 
|  | 98 | +  val scope_of_saved_token : | 
|  | 99 | +    saved_token -> | 
|  | 100 | +    scope list | 
|  | 101 | + | 
|  | 102 | +  (** Return the secret key used to sign the JWT. *) | 
|  | 103 | +  val secret_key_of_saved_token : | 
|  | 104 | +    saved_token -> | 
|  | 105 | +    string | 
|  | 106 | + | 
|  | 107 | +  (** Return the number of passed cycle. *) | 
|  | 108 | +  val counter_of_saved_token    : | 
|  | 109 | +    saved_token -> | 
|  | 110 | +    int ref | 
|  | 111 | + | 
|  | 112 | +  (** Return [true] if the token already exists *) | 
|  | 113 | +  val token_exists              : | 
|  | 114 | +    saved_token                 -> | 
|  | 115 | +    bool | 
|  | 116 | + | 
|  | 117 | +  (* Generate a token value *) | 
|  | 118 | +  val generate_token_value      : | 
|  | 119 | +    unit                        -> | 
|  | 120 | +    string | 
|  | 121 | + | 
|  | 122 | +  (* Generate a new token *) | 
|  | 123 | +  val generate_token            : | 
|  | 124 | +    id_client:Os_types.OAuth2.Client.id -> | 
|  | 125 | +    userid:Os_types.User.id             -> | 
|  | 126 | +    scope:scope list                    -> | 
|  | 127 | +    saved_token Lwt.t | 
|  | 128 | + | 
|  | 129 | +  (** Save a token *) | 
|  | 130 | +  val save_token                : | 
|  | 131 | +    saved_token                 -> | 
|  | 132 | +    unit | 
|  | 133 | + | 
|  | 134 | +  (** Remove a token. *) | 
|  | 135 | +  val remove_saved_token        : | 
|  | 136 | +    saved_token                 -> | 
|  | 137 | +    unit | 
|  | 138 | + | 
|  | 139 | +  (** Return the saved token assigned to the client with given ID and | 
|  | 140 | +      value. | 
|  | 141 | +   *) | 
|  | 142 | +  val saved_token_of_id_client_and_value : | 
|  | 143 | +    Os_types.OAuth2.Server.id -> | 
|  | 144 | +    string                    -> | 
|  | 145 | +    saved_token | 
|  | 146 | + | 
|  | 147 | +  (* List all saved tokens *) | 
|  | 148 | +  val list_tokens               : | 
|  | 149 | +    unit                        -> | 
|  | 150 | +    saved_token list | 
|  | 151 | + | 
|  | 152 | +  (** Return the saved token as a JSON. Used to send to the client. *) | 
|  | 153 | +  val saved_token_to_json       : | 
|  | 154 | +    saved_token                 -> | 
|  | 155 | +    Yojson.Safe.json | 
|  | 156 | +end | 
| 115 | 157 | 
 | 
| 116 | 158 | (** Basic module for scopes. | 
|  | 159 | +
 | 
| 117 | 160 |     [check_scope_list scope_list] returns [true] if every element in | 
| 118 | 161 |     [scope_list] is an available scope value. | 
| 119 | 162 |     If the list contains only [OpenID] or if the list doesn't contain [OpenID] | 
| 120 |  | -    (mandatory scope in RFC), returns [false]. | 
|  | 163 | +    (mandatory scope in RFC), it returns [false]. | 
| 121 | 164 |     If an unknown scope value is in list (represented by [Unknown] value), | 
| 122 |  | -     returns [false]. | 
|  | 165 | +    it returns [false]. | 
| 123 | 166 |  *) | 
| 124 | 167 | 
 | 
|  | 168 | +(** Basic scope *) | 
| 125 | 169 | module Basic_scope : Os_oauth2_server.SCOPE | 
| 126 | 170 | 
 | 
|  | 171 | +(** MakeIDToken (Scope) returns a module of type {!IDTOKEN} with the type | 
|  | 172 | +    {!IDTOKEN.scope} equals to {!Scope.scope}. | 
|  | 173 | +
 | 
|  | 174 | +    Tokens are represented as a record with exactly the same fields available in | 
|  | 175 | +    the inferface {!IDTOKEN}. | 
|  | 176 | +
 | 
|  | 177 | +    The token type is always ["bearer"]. | 
|  | 178 | +
 | 
|  | 179 | +    The related JSON contains the fields: | 
|  | 180 | +    - ["token_type"] with value ["bearer"]. | 
|  | 181 | +    - ["token"] with the token value. | 
|  | 182 | +    - ["expires_in"] with the value [cycle_duration * number_of_cycle] i.e. 600 | 
|  | 183 | +    seconds. | 
|  | 184 | +    - ["id_token"] with the JWT. | 
|  | 185 | +
 | 
|  | 186 | +
 | 
|  | 187 | +    NOTE: If you want to implement another type of tokens, you need to implement | 
|  | 188 | +    another functor (with the [Scope.scope] type dependency) which returns a | 
|  | 189 | +    module of type {!IDTOKEN}. The resulting module can be given as parameter to | 
|  | 190 | +    the function {!Os_oauth2_server.MakeServer}. | 
|  | 191 | + *) | 
| 127 | 192 | module MakeIDToken : functor | 
| 128 | 193 |   (Scope : Os_oauth2_server.SCOPE) -> | 
| 129 | 194 |   (IDTOKEN with type scope = Scope.scope) | 
| 130 | 195 | 
 | 
|  | 196 | +(** Basic ID Token based on the scope from {!Basic_scope}. *) | 
| 131 | 197 | module Basic_ID_token | 
| 132 | 198 |   : (IDTOKEN with | 
| 133 | 199 |     type scope = Basic_scope.scope) | 
| 134 | 200 | 
 | 
|  | 201 | +(** [Basic (Scope) (Token)] returns a module representing a OpenID Connect | 
|  | 202 | +    server. The available scopes come from {!Scope.scope} and the token related | 
|  | 203 | +    functions, types and representation come from {!Token}. | 
|  | 204 | +
 | 
|  | 205 | +    As an OpenID Connect server is based on an OAuth2.0, the server is generated | 
|  | 206 | +    with {!Os_oauth2_server.MakeServer}. | 
|  | 207 | + *) | 
| 135 | 208 | module Basic : (Os_oauth2_server.SERVER with | 
| 136 | 209 |   type scope = Basic_scope.scope and | 
| 137 | 210 |   type saved_token = Basic_ID_token.saved_token | 
|  | 
0 commit comments