|
| 1 | +## Modular Auth notes |
| 2 | + |
| 3 | +- Authentication service |
| 4 | + - Each service will have it's own repository to hold implementation |
| 5 | + |
| 6 | + - Things to consider |
| 7 | + - ui |
| 8 | + - Forms or any view component should be defined for each component. |
| 9 | + - Idealy accounts/client will passed on the ui config method and it will then be used by the ui components |
| 10 | + - data store |
| 11 | + - Store auth details for document based stores |
| 12 | + - How indexes are handled? |
| 13 | + - map to relational entries (for sql implmentation) |
| 14 | + - added endpoints |
| 15 | + - should expose the express/koa/hapi middleware if needed. |
| 16 | + |
| 17 | + - Register service plugins |
| 18 | + - Register on client |
| 19 | + - Register on server |
| 20 | + - Suggested API |
| 21 | + ```typescript |
| 22 | + // client code |
| 23 | + const accountsClient = new AccountsClient({ |
| 24 | + authServices: { |
| 25 | + local: PasswordService, |
| 26 | + google: GoogleOAuth, |
| 27 | + sso: CustomSSO, |
| 28 | + ...moreAuthServices |
| 29 | + } |
| 30 | + }); |
| 31 | + |
| 32 | + // server code |
| 33 | + const accountsClient = new AccountsClient({ |
| 34 | + authServices: { |
| 35 | + local: PasswordService, |
| 36 | + google: GoogleOAuth, |
| 37 | + sso: CustomSSO, |
| 38 | + ...moreAuthServices |
| 39 | + } |
| 40 | + }); |
| 41 | + ``` |
| 42 | + |
| 43 | + - Auth details (Password, Token, Face, Fingerprint, DeviceID, OAuth2) |
| 44 | + - Authenticate details |
| 45 | + - Register auth details for user |
| 46 | + - Recover/Override details |
| 47 | + - It seems as though the only strategy that requiers this kind of logic will be a local strtegy |
| 48 | + |
| 49 | + - Authenticate detail suggested API |
| 50 | + ```typescript |
| 51 | + login(serviceName: string, authDetails: Object): Promise<SessionToken> |
| 52 | + ``` |
| 53 | + |
| 54 | + - Register auth details suggested API (Some strategies will only allow that on the server) |
| 55 | + ```typescript |
| 56 | + register(serviceName: string, authDetails: Object): Promise<UserObject> |
| 57 | + ``` |
| 58 | + |
| 59 | +In order to spot potential abstractions on the different authentication strategies I've tried to breakdown the flows in my own words. It might be helpful for someone. |
| 60 | + |
| 61 | +### Local strategy (Password / Fingerprint / Pattern) |
| 62 | + |
| 63 | +- Before authorization the client knows nothing and it shows the usraer a form or some kind of input mechanism that allows |
| 64 | +the user to write his identity (Phone / Username / Email) and an authorization information (Password / Fingerprint / Pattern) |
| 65 | + |
| 66 | +- After the user inserts his auth detail accounts/client will send a request of `login` to the accounts/server |
| 67 | + |
| 68 | +- accounts/server will then validate the user details and send back the SessionToken object. |
| 69 | + |
| 70 | +### OAuth2 breakdown (Used this [helpfull resource](https://alexbilbie.com/guide-to-oauth-2-grants/) by Alex Bilbie) |
| 71 | + |
| 72 | +- Before authentication client app needs to know |
| 73 | + - `client_id` (You get this when you register the your app and could be hardcoded in the client code) |
| 74 | + - authorization url (Like google oauth endpoint) |
| 75 | + - `scope` (access to what resources) |
| 76 | + |
| 77 | +- When the user clicks authenticate button he is redirected to the autorization url. |
| 78 | + |
| 79 | +- The request has the following query params: |
| 80 | + - `response_type` that has the constant value `code` |
| 81 | + - `client_id` explaind above |
| 82 | + - `scope` explained above |
| 83 | + - Optional - `redirect_url` overrides the url provided with registration of the app |
| 84 | + - Optional - `state` CSRF token to validate when the user is redirected back |
| 85 | + |
| 86 | +- On the other site (e.g. google login form) the user is identified by any form and then |
| 87 | +gets redirected back to the client site with the authorization `code` and `state`. |
| 88 | + |
| 89 | +- The `redirect_url` would then be handled by: |
| 90 | + |
| 91 | + - accounts/client |
| 92 | + - When redirected back to the app it will use accounts/client to transfer authorization `code` to the server using any transport. |
| 93 | + - accounts/server |
| 94 | + - Should offer a method to pass in the authorization `code` and move to the next step of the OAuth flow. |
| 95 | + |
| 96 | +> Handling this as a separate rest endpoint where the server gets the properties only and the client is not a part of the porcess, means that transports like `graphql` or `ws` will be rendered useless for this part, and so I think we may need to expose a helper method and let the app developers decide what he would like to do with it. In cases where they will not use our accounts/client they can then use our `rest-express` transport or even create their own endpoint or means of calling this method. |
| 97 | + |
| 98 | +- accounts/server now needs to trade the authorization `code` for a token that will be used for any resource request. |
| 99 | +- The trade request is made from the server to the authorization server (e.g. google) using POST and icludes the following fields: |
| 100 | + - `grant_type` that has a constant value of `authorization_code` |
| 101 | + - `client_id` same as before |
| 102 | + - `client_secret` (this is a secret string that is issued together with the `client_id` but should remain on your server) |
| 103 | + - `redirect_uri` The same url that the client was redirected to |
| 104 | + - `code` authorization code the server just got |
| 105 | + |
| 106 | +- The server will get in response the following fields: |
| 107 | + - `token_type` Some kind of constant that represents the type of the token and how it should be used. Most times it will be `Bearer` |
| 108 | + - `expires_in` A numeric value that states the expiration time of the token in seconds |
| 109 | + - `access_token` The token itself |
| 110 | + - `refresh_token` A token that alows the server to get a new access token after it is expired |
| 111 | + |
| 112 | +- OAuth2 flow ends here but we still need to create or authenticate the user in our app. |
| 113 | + |
| 114 | +- For creating our session, accounts/server should require data about the user like `email` or `username` and any additional profile inforamtion the developer would like. |
| 115 | + |
| 116 | +- accounts/server will then create a new user record or attach to an existing user with other authorization service configured and attach `access_token` response object as means to re-authenticate or get data at later time if needed. |
| 117 | + |
| 118 | +### Custom SSO |
| 119 | + |
| 120 | +In this flow the app developer will have an external service that does validation using it's own local authorization details. |
| 121 | +accounts/server should be able to trust this external service in some way and issue session tokens for clients after the external service has checked the identity. |
| 122 | + |
| 123 | +- The user submits authentication details on an external app |
| 124 | + |
| 125 | +- After authorization he is then redirected with some auth token to our app |
| 126 | + |
| 127 | +- The accounts/client app will then call `login` with the given auth token |
| 128 | + |
| 129 | +- accounts/server will then validate the auth token against the SSO service |
| 130 | + |
| 131 | +- If validated it will return a session token to the client |
0 commit comments