|
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