Authentification » History » Version 2
Eric Vieillevigne, 05/12/2015 01:47 PM
| 1 | 2 | Eric Vieillevigne | h1. Authentication |
|---|---|---|---|
| 2 | 1 | jerome bonnet | |
| 3 | h1. 1 Principles |
||
| 4 | |||
| 5 | h2. 1.1 Account |
||
| 6 | |||
| 7 | In the platform a user having family data is called an account. An account may be authenticated on the platform and has: |
||
| 8 | 2 | Eric Vieillevigne | * One or several "account identifiers" |
| 9 | 1 | jerome bonnet | * A Password: Password of a user is stored in the databased with a BCrypt Hash |
| 10 | |||
| 11 | h2. 1.2 Account identifiers |
||
| 12 | |||
| 13 | Each user's account on the platform is identified by one or several identifiers. Identifier properties are: |
||
| 14 | |||
| 15 | * The 'type', which is an enum that may be: |
||
| 16 | > * Email: an email |
||
| 17 | > * Msisdn: a phone number (not used at the moment) |
||
| 18 | > * ExternalId: the id of an external system (for SSO integration) |
||
| 19 | > * Login: a login (free-form string) |
||
| 20 | > * AccessToken: a random string being an identifier for a cryptographic authentication token |
||
| 21 | > * SOMETHING_ELSE: reserved for extension mechanism. |
||
| 22 | |||
| 23 | * The 'value', which correspond to the type and must be totally unique across all users |
||
| 24 | |||
| 25 | h2. 1.3 Type of Authentication |
||
| 26 | |||
| 27 | The server APIs falls into two different categories: |
||
| 28 | |||
| 29 | - _*Account-based api*_ : |
||
| 30 | > API where the api call is relative to an account, such as wall/get (retrieve wall messages). Such apis do always work on the user's account data or on the behalf of the Account, and the account in question is not passed as an explicit argument to the api. It is an implicit argument. |
||
| 31 | > Such apis mandate the caller to be authenticated and that the authentication corresponds to an account on the platform. |
||
| 32 | |||
| 33 | - _*Non-account-based api*_ , such as createAccount: |
||
| 34 | > API which does not consider the logged account as an implicit argument. Such apis may mandate the client (or the calling application) to be authenticated, but does not mandate that the authentication correspond to an account on the platform. For instance, the client, or an administrator, may be authenticated to perform such api calls, but they do not automatically correspond to an account. |
||
| 35 | |||
| 36 | 2 | Eric Vieillevigne | As a result, an api call can be authenticated in two fashions: |
| 37 | 1 | jerome bonnet | |
| 38 | - _*Client Authentication*_ |
||
| 39 | 2 | Eric Vieillevigne | > Authentication recognize the calling application and associated right to call one or another api |
| 40 | 1 | jerome bonnet | |
| 41 | - _*Account Authentication*_ |
||
| 42 | > Authentication recognize the account and therefore enable calling account-based api. |
||
| 43 | |||
| 44 | > Both authentication can be available at the same time. |
||
| 45 | |||
| 46 | 2 | Eric Vieillevigne | h2. 1.4 Client authentication |
| 47 | 1 | jerome bonnet | |
| 48 | 2 | Eric Vieillevigne | h2. 1.4.1 Api Access Right Ruleset |
| 49 | 1 | jerome bonnet | |
| 50 | 2 | Eric Vieillevigne | An Access Right ruleset is a set of rules indicating if each api is available or not. |
| 51 | For instance the ruleset "WEB" indicate that most of the API are accessible by this ruleset but that some administration api are not. |
||
| 52 | Those rulesets are configured in the resource file accessrights.xml |
||
| 53 | 1 | jerome bonnet | |
| 54 | 2 | Eric Vieillevigne | h2. 1.4.2 Clients Id and Secret |
| 55 | 1 | jerome bonnet | |
| 56 | 2 | Eric Vieillevigne | Clients are authenticated by a *clientId* and a *clientSecret*, similarly as a login/password for a user. |
| 57 | 1 | jerome bonnet | |
| 58 | 2 | Eric Vieillevigne | Each client are allocated a given set of access rights that will correspond to: |
| 59 | # Access Right RuleSet : a configured set of access right to indicate the authorized and forbidden apis |
||
| 60 | # Client-type : Confidential or Public, indicating if the |
||
| 61 | # RedirectUrl : start of the authorized url redirection, needed for the web authentification |
||
| 62 | # isOAuth2PasswordBasedAuthorized: indicate if the client is authorized to transport login/password information of the user |
||
| 63 | # name: the real name of the client |
||
| 64 | 1 | jerome bonnet | |
| 65 | 2 | Eric Vieillevigne | Clients are authenticated with Oauth2 in a standard way and with WEB authentication. Legacy authentication does not support client authentication. |
| 66 | |||
| 67 | h3. 1.4.3 Client authorization errors |
||
| 68 | |||
| 69 | Whenever an API is called without client authentification and is not in the NOAUTHENT Access Right ruleset, the following error is returned to the caller: |
||
| 70 | 501 : FizAccountNotFoundInSessionException |
||
| 71 | 509 : FizApiKeyInsufficientRightsException |
||
| 72 | |||
| 73 | h2. 1.5 HTTP Sessions |
||
| 74 | |||
| 75 | 1 | jerome bonnet | The api support (and even requires for performance reason) a session concept over HTTP. |
| 76 | |||
| 77 | At any time during an HTTP api call the server _MAY_ respond with an additional Set-Cookie HTTP header, setting a JSESSIONID http cookies. |
||
| 78 | At any subsequent call the the server, the client _MUST_ return the JSESSION id cookie, and ONLY this cookie. The cookie time-to-live on the client may be short and shall, if possible, correspond to a user session, if applicable. |
||
| 79 | |||
| 80 | At any time the server may invalidate an HTTP session and resend a JSESSIONID. However the server shall implement an HTTP session time-to-live based on a 30 minutes timeout after the lastest access. |
||
| 81 | |||
| 82 | 2 | Eric Vieillevigne | h1. 2 LEGACY authentication based on the http session |
| 83 | 1 | jerome bonnet | |
| 84 | > This Authentication scheme will be deprecated in the future, because it does not support Client Authentication, and is poorly secure. |
||
| 85 | |||
| 86 | This authentication scheme consist in calling the log2in api priori to any other account-based API. Non account-based apis are left unauthenticated. |
||
| 87 | By calling the log2in api, the identifier/password are passed to the system and verified. The identifier must correspond to an account's identifier and the password must pass the hash test of the corresponding account. |
||
| 88 | |||
| 89 | If the authentication is successful, the current HTTP session will become Account Authenticated up to the end of the HTTP Session. |
||
| 90 | |||
| 91 | The api log2out may be called to remove the account authentication from the current HTTP Session. This will also invalidate the current HTTP session. |
||
| 92 | |||
| 93 | Because an http session can be invalidated by the server at any time (or almost at any time, the server _SHALL_ implement a 30 minutes timeouts after the last call on a session), the client _SHALL_ be ready to manage any 501:FizAccountNotFoundInSessionException errors and redo a log2in call. |
||
| 94 | |||
| 95 | 2 | Eric Vieillevigne | When this authentication scheme is used, the Access Right Ruleset used (indicating which api can be called and which cannot) is LEGACY |
| 96 | |||
| 97 | 1 | jerome bonnet | h2. 2.1 Authorization errors: |
| 98 | |||
| 99 | Whenever an account-based api is called without an account authentication, the following error will be returned to the caller: |
||
| 100 | 501 : FizAccountNotFoundInSessionException |
||
| 101 | |||
| 102 | 2 | Eric Vieillevigne | h2. 2.2 ISSUES WITH HTTP SESSION AUTHENTIFICATION |
| 103 | |||
| 104 | *MERGE METHOD* : merge method in account are not compatible with header auths |
||
| 105 | |||
| 106 | *RESET PASSWORD* : must be authenticated with a email token, which is one-time use token |
||
| 107 | |||
| 108 | *INVITATION* : must be authenticated with an email token, which may be used several time during a given period |
||
| 109 | |||
| 110 | *CREATEACCOUNT* : create account API shall return an AccessToken instead of letting the HTTP SESSION API Alive |
||
| 111 | |||
| 112 | *PREVIOUSLOGINDATE* : We store the PREVIOUS LOGIN DATE in the http session to perform some magic, this must be REMOVED |
||
| 113 | However this is used in the WEB for the numbers in the notification badge in the family menu, this MUST be redesigned anyway (or not ?) it can still be used if it is only on the WEB. |
||
| 114 | |||
| 115 | *LASTLOGINDATE* : we need to change to policy of this update |
||
| 116 | WE MUST MOVE THE CODE FROM AccountLoginApiImpl.loginAccountFromIdentifier to somewhere else... |
||
| 117 | |||
| 118 | 1 | jerome bonnet | h1. 3 OAuth2 Authentication |
| 119 | |||
| 120 | h2. 3.1 OAuth2 Presentation |
||
| 121 | |||
| 122 | The system is able to use various (but not all) OAuth2 authentication scenarios to provide access to account-based apis. |
||
| 123 | |||
| 124 | 2 | Eric Vieillevigne | > Based on The OAuth 2.0 Authorization Protocol (draft-ietf-oauth-v2-31) (see http://datatracker.ietf.org/doc/draft-ietf-oauth-v2/ ) |
| 125 | 1 | jerome bonnet | |
| 126 | The principle is that the client must obtain an Access-Token and a Refresh-Token from the server, and then use the Access-Token to authenticate itself and use account-based apis. In order to obtain the Access-Token and the Refresh-Token, the client must use HTTPS/TLS. |
||
| 127 | |||
| 128 | The type of access-token managed by the server is "MAC Access Authentication" . |
||
| 129 | |||
| 130 | > Based on HTTP Authentication: MAC Access Authentication, draft-ietf-oauth-v2-http-mac-01 (see http://datatracker.ietf.org/doc/draft-ietf-oauth-v2-http-mac/ ) |
||
| 131 | |||
| 132 | The MAC Access Token is secure enough in order to be used on plain http connection instead of HTTPS/TLS. However his time-to-live is medium-lived (ie several days). When an Access Token is obsolete, the client must use the Refresh Token to obtain a new Access Token, using HTTPS/TLS. The Refresh Token is much more long lived (several years). |
||
| 133 | |||
| 134 | The Access-Token is used by signing an http request with the token secret with a hmac algorithm and put the signature in the Authorization Header of the http request. |
||
| 135 | |||
| 136 | 2 | Eric Vieillevigne | > Based on HTPT Authentication: Bearer : draft-ietf-oauth-v2-bearer-22.pdf (see http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-23 ) |
| 137 | |||
| 138 | 1 | jerome bonnet | > Note that this authentication mechanism does not aleviate the client from handling the HTTP Sessions cookies. However the HTTP sessions will be transparently recreated and re-authenticated and the usage of the log2in api is not necessary anymore. |
| 139 | |||
| 140 | In order to retrieve the Access-Token or the Refresh-Token, several scenario are possible, depending on the type of application, the type of client, etc... |
||
| 141 | The following scenario are implemented: |
||
| 142 | |||
| 143 | 2 | Eric Vieillevigne | > Exchange against login/password (for privilegied clients) |
| 144 | 1 | jerome bonnet | |
| 145 | 2 | Eric Vieillevigne | The client must use the " log2generateaccesstokenbypassword " api to exchange the login/password of the user with an access token. |
| 146 | 1 | jerome bonnet | |
| 147 | 2 | Eric Vieillevigne | > Exchange against a validation token (for privilegied clients) |
| 148 | |||
| 149 | The client must use the " log2generateaccesstokenbyvalidationtoken " api to exchange a validation token with an access token. |
||
| 150 | |||
| 151 | |||
| 152 | |||
| 153 | 1 | jerome bonnet | h2. 3.2 OAuth2 error codes |
| 154 | |||
| 155 | When an access token is required and missing the following error is returned to the client: |
||
| 156 | |||
| 157 | <pre> |
||
| 158 | HTTP/1.1 401 Unauthorized |
||
| 159 | WWW-Authenticate: MAC |
||
| 160 | </pre> |
||
| 161 | |||
| 162 | 2 | Eric Vieillevigne | or |
| 163 | |||
| 164 | <pre> |
||
| 165 | HTTP/1.1 401 Unauthorized |
||
| 166 | WWW-Authenticate: Bearer |
||
| 167 | </pre> |
||
| 168 | |||
| 169 | 1 | jerome bonnet | When an access token is obsolete the following error is returned to the client: |
| 170 | |||
| 171 | <pre> |
||
| 172 | HTTP/1.1 401 Unauthorized |
||
| 173 | WWW-Authenticate: MAC Expired |
||
| 174 | </pre> |
||
| 175 | |||
| 176 | For other errors the WWW-Authenticate will provide various error messages. |
||
| 177 | |||
| 178 | h2. 3.3 Compatibility with authentication based on the http session |
||
| 179 | |||
| 180 | Normally, resource protected by OAuth will deny access of any request that do not have a valid Authorization Header. |
||
| 181 | However, when using the "Simple login/password authentication based on the http session" (see #2.0) concurrently, we have the following policy: |
||
| 182 | |||
| 183 | For accessing account-based apis: |
||
| 184 | # Any http request passed with an http session identified authentified with the "Simple login/password authentication based on the http session" will not require the OAuth 2.0 authentification |
||
| 185 | # Any other http request will requires the OAuth Authorization http header |
||
| 186 | |||
| 187 | For non-account-based apis, for the moment they are left unauthentified while we implement security on non-account based apis. |
||
| 188 | |||
| 189 | 2 | Eric Vieillevigne | h2. 3.4 Getting an Access Token for privilegied application |
| 190 | 1 | jerome bonnet | |
| 191 | 2 | Eric Vieillevigne | h3. log2generateaccesstokenbypassword |
| 192 | 1 | jerome bonnet | |
| 193 | 2 | Eric Vieillevigne | The client must: |
| 194 | > > Provide a client_id and client_secret to identify itself (using basic_auth or client_id and client_secret http parameters) |
||
| 195 | > > Provide a deviceId (as in the devicesetconfig api) to identify the device |
||
| 196 | > > The type of desired token (either Bearer or Mac) |
||
| 197 | > > Must perform his call using HTTPS |
||
| 198 | 1 | jerome bonnet | |
| 199 | 2 | Eric Vieillevigne | Example: |
| 200 | <pre> |
||
| 201 | GET /api?a01call=log2generateaccesstokenbypassword&a01identifier=margesimpsontest&a01password=marge&a01tokentype=Bearer&a01deviceId=1-2-3-4-5&client_id=1-2-3-3-2&client_secret=azerty HTTP/1.1 |
||
| 202 | </pre> |
||
| 203 | 1 | jerome bonnet | |
| 204 | 2 | Eric Vieillevigne | In this example, the client gets his accessToken by using the user's credentials margesimpsontest/marge . |
| 205 | |||
| 206 | > His device is identified by 1-2-3-4-5 |
||
| 207 | > The client key is 1-2-3-3-2 / azerty |
||
| 208 | > The requested token type is "Bearer" |
||
| 209 | |||
| 210 | For the response, see 3.6 |
||
| 211 | |||
| 212 | h3. log2generateaccesstokenbyvalidationtoken |
||
| 213 | |||
| 214 | The client must: |
||
| 215 | > > Provide a client_id and client_secret to identify itself (using basic_auth or client_id and client_secret http parameters) |
||
| 216 | > > Provide a deviceId (as in the devicesetconfig api) to identify the device |
||
| 217 | > > The type of desired token (either Bearer or Mac) |
||
| 218 | > > Must perform his call using HTTPS |
||
| 219 | |||
| 220 | Example: |
||
| 221 | <pre> |
||
| 222 | GET /api?a01call=log2generateaccesstokenbyvalidationtoken&a01validationtoken=123token123&a01tokentype=Bearer&a01deviceId=1-2-3-4-5&client_id=1-2-3-3-2&client_password=azerty HTTP/1.1 |
||
| 223 | </pre> |
||
| 224 | |||
| 225 | In this example, the client gets his accessToken by using the validation token 123token123 . |
||
| 226 | |||
| 227 | > His device is identified by 1-2-3-4-5 |
||
| 228 | > The client key is 1-2-3-3-2 / azerty |
||
| 229 | > The requested token type is "Bearer" |
||
| 230 | |||
| 231 | For the response, see 3.6 |
||
| 232 | |||
| 233 | 1 | jerome bonnet | h2. 3.5 Refresh Token usage |
| 234 | |||
| 235 | In order to use the refresh token, the client must present the refresh token to the /token endpoint in HTTPS/TLS. |
||
| 236 | See #6 of IETF OAuth specification. |
||
| 237 | |||
| 238 | Example: |
||
| 239 | <pre> |
||
| 240 | POST /token HTTP/1.1 |
||
| 241 | Host: server.example.com |
||
| 242 | Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW |
||
| 243 | Content-Type: application/x-www-form-urlencoded;charset=UTF-8 |
||
| 244 | grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA |
||
| 245 | </pre> |
||
| 246 | |||
| 247 | 2 | Eric Vieillevigne | Note: Authorization headers shall contains the clientId/clientSecret for the client authorization. For there, all access performed with the Access-token will be considered as client-authenticated with those credentials. It is mandatory. |
| 248 | |||
| 249 | 1 | jerome bonnet | h2. 3.6 Access-Token response format |
| 250 | |||
| 251 | As defined in both ietf specification, the access token will be returned in JSON. |
||
| 252 | The only type of access-token managed is "mac". |
||
| 253 | The only type of max algorithm managed is "hmac-sha-1". |
||
| 254 | |||
| 255 | <pre> |
||
| 256 | HTTP/1.1 200 OK |
||
| 257 | Content-Type: application/json;charset=UTF-8 |
||
| 258 | Cache-Control: no-store |
||
| 259 | Pragma: no-cache |
||
| 260 | { |
||
| 261 | "access_token":"2YotnFZFEjr1zCsicMWpAA", |
||
| 262 | "token_type":"mac", |
||
| 263 | "expires_in":3600, |
||
| 264 | "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", |
||
| 265 | "mac_key":"AEZRDF41424aezraezr", |
||
| 266 | "mac_algorithm","hmac-sha-1" |
||
| 267 | } |
||
| 268 | </pre> |
||
| 269 | |||
| 270 | 2 | Eric Vieillevigne | h2. 3.7 Using the Bearer access-token to generate Authorization request. |
| 271 | 1 | jerome bonnet | |
| 272 | 2 | Eric Vieillevigne | It is fairly simple. |
| 273 | You just need to add an http basic-auth authorization header. |
||
| 274 | Example: |
||
| 275 | |||
| 276 | <pre> |
||
| 277 | POST /API HTTP/1.1 |
||
| 278 | Authorization: Bearer aezraezrez:eazrraezraezraez |
||
| 279 | </pre> |
||
| 280 | |||
| 281 | |||
| 282 | h2. 3.8 Using the MAC SHA1 access-token to generate Authorization request. |
||
| 283 | |||
| 284 | 1 | jerome bonnet | It is actually all explained here : draft-ietf-oauth-v2-http-mac-01 , but I will summarize the procedure here: |
| 285 | |||
| 286 | # Generate the request Timetsamp in seconds |
||
| 287 | # Generate a random number to be used as a nonce |
||
| 288 | # From the request being done, extract the HOST, PORT, HTT_METHOD, and FULL_PATH_OF_QUERY |
||
| 289 | # Concatenate all Timestamp, nonce, and information extracted from request into a string |
||
| 290 | # Compute the hmac of the concatenated string with the mac_key |
||
| 291 | # Generate and add an Authorization header in the http request |
||
| 292 | |||
| 293 | The format of the Authorization header is: |
||
| 294 | <pre> |
||
| 295 | Authorization: MAC id="h480djs93hd8", |
||
| 296 | ts="1336363200", |
||
| 297 | nonce="dj83hs9s", |
||
| 298 | mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM=" |
||
| 299 | </pre> |
||
| 300 | |||
| 301 | The id is the "access_token" value, the ts is the timestamp, the nonce is (well) the nonce, and the mac is the result of the hmac computation. |
||
| 302 | |||
| 303 | 2 | Eric Vieillevigne | h1. 5 WEB Oauth Authentification |
| 304 | 1 | jerome bonnet | |
| 305 | 2 | Eric Vieillevigne | Web application authentication workflow is a derivated version of the oAuth2 protocol, but that does not requires the Authorization server to handle the display of the webpage himself. |
| 306 | 1 | jerome bonnet | |
| 307 | 2 | Eric Vieillevigne | The idea is to mandate that the client is authenticated (via his clientId/clientSecret) without exposing the clientSecret to the browser (note that in oAuth browser=user-agent). |
| 308 | 1 | jerome bonnet | |
| 309 | 2 | Eric Vieillevigne | In order to illustrate the process, we take the following hypothesis: |
| 310 | # User-Agent is a firefox browser, and it runs the main load of the application developped in Javascript. |
||
| 311 | # Webapp is build with PHP, and holds the secret. The secret is protected because it is sent to the User-Agent. |
||
| 312 | |||
| 313 | |||
| 314 | 1 | jerome bonnet | <pre> |
| 315 | 2 | Eric Vieillevigne | |
| 316 | +----------+ |
||
| 317 | | User | |
||
| 318 | | | |
||
| 319 | +----------+ |
||
| 320 | ^ |
||
| 321 | | |
||
| 322 | (C) |
||
| 323 | +----|-----+ User Login/Pwd +---------------+ |
||
| 324 | | +----(D)-- return JSESSIONID ---->| | |
||
| 325 | | User- | | FizApi | |
||
| 326 | | Agent +<---(E)-- JSESSIONID ------------| Server | |
||
| 327 | | | | | |
||
| 328 | | | | | |
||
| 329 | +-|----|---+ +---------------+ |
||
| 330 | | | ^ v |
||
| 331 | (A) (F) | | |
||
| 332 | | | | | |
||
| 333 | ^ v | | |
||
| 334 | +---------+ | | |
||
| 335 | | |>---(B)-- State Random Cypher---------' | |
||
| 336 | | PHP | return StateSecret | |
||
| 337 | | | | |
||
| 338 | | |>---(G)----- JSESSIONID -------------------' |
||
| 339 | +---------+ (client ID + Secret) |
||
| 340 | |||
| 341 | 1 | jerome bonnet | </pre> |
| 342 | |||
| 343 | 2 | Eric Vieillevigne | A: User-Agent performs the first request to the PHP server to retrieve all the Javascript code of the webapp. |
| 344 | B: In order to initialize this Javascript, the PHP server is asking the FizApi server to generate a sessionSecret from a State Random Cypher (random generated by PHP) |
||
| 345 | A end: The PHP server is embedding the StateSecret in the Javascript code and returns the Javascript code to the user-agent |
||
| 346 | Because the sessionSecret is embedded in the Javascript, it will render screen-scraping more difficult, it shall be buried deep inside the Javascript, as obfuscated as possible. |
||
| 347 | 1 | jerome bonnet | |
| 348 | 2 | Eric Vieillevigne | C: The Javascript within the user-agent is presenting a "html form" to the user asking for his login/password and directed to the FizApi Server |
| 349 | The form contains the State Random Cypher |
||
| 350 | The user is submitting his login/password |
||
| 351 | |||
| 352 | D: The user-agent is submitting the form to the FizApi Server (directly without Javascript for Safari compatibility) |
||
| 353 | Containing the login, password, and State Random Cypher. |
||
| 354 | |||
| 355 | E: The FizApi Server is validating the login/password, if it is valid, it opens a WEB api session and return the session identifier to the User-Agent. |
||
| 356 | The session is still not client authenticated. |
||
| 357 | |||
| 358 | F: The Javascript in the user-agent is submitting to PHP the JSESSIONID and the StateSecret |
||
| 359 | |||
| 360 | G: The PHP is submitting the triplet (StateSecret,JSESSIONID,clientId+ClientSecret) in order to validate the JSESSIONID on the FizApi Server |
||
| 361 | The FizApi Server is validating that |
||
| 362 | 1) The StateSecret corresponds to the State Random Cypher for the same JSESSIONID, |
||
| 363 | 2) the clientId+ClientSecret are valid |
||
| 364 | The FizApi Server grants the session with the JSESSIONID with corresponding client Authorization. Any calls made by the user-agent to the FizApi server with this JESSIONID will be authorized. |