diff options
author | adamscmRH <chadams@redhat.com> | 2018-02-23 18:42:44 +0100 |
---|---|---|
committer | adamscmRH <chadams@redhat.com> | 2018-02-23 20:10:29 +0100 |
commit | 87350e10142ada31bc181fc3dd0c66061b2c7cbc (patch) | |
tree | cb7d5cc1e93c8dbcd695eb0ae0365eac4987abe0 /docs/auth | |
parent | fixes app token endpoint (diff) | |
download | awx-87350e10142ada31bc181fc3dd0c66061b2c7cbc.tar.xz awx-87350e10142ada31bc181fc3dd0c66061b2c7cbc.zip |
prelim update to docs
Diffstat (limited to 'docs/auth')
-rw-r--r-- | docs/auth/oauth.md | 110 | ||||
-rw-r--r-- | docs/auth/session.md | 28 |
2 files changed, 123 insertions, 15 deletions
diff --git a/docs/auth/oauth.md b/docs/auth/oauth.md index dc9e9860e4..8f46dcc8af 100644 --- a/docs/auth/oauth.md +++ b/docs/auth/oauth.md @@ -86,3 +86,113 @@ token scope; or POSTing to `/api/applications/<pk>/tokens/` by providing only `s the parent application will be automatically linked. # More Docs Coming Soon +Note a default new application will be created for each new user. So each new user is supposed to see +at least one application available to them. + +Tokens, on the other hand, are resources used to actually authenticate incoming requests and mask the +permissions of underlying user. Tokens can be created by POSTing to `/api/v2/tokens/` +endpoint by providing `application` and `scope` fields to point to related application and specify +token scope; or POSTing to `/api/applications/<pk>/tokens/` by providing only `scope`, while +the parent application will be automatically linked. + +Individual tokens will be accessible via their primary keys: +`/api/<version>/me/oauth/tokens/<primary key of a token>/`. Here is a typical token: +``` +{ + "id": 17, + "type": "access_token", + "url": "/api/v2/me/oauth/tokens/17/", + "related": { + "user": "/api/v2/users/1/", + "application": "/api/v2/me/oauth/applications/4/", + "activity_stream": "/api/v2/me/oauth/tokens/17/activity_stream/" + }, + "summary_fields": { + "application": { + "id": 4, + "name": "admin's token", + "client_id": "D6SwhKbfp2LuUjkmiUpMMYFyNqhpv5PTVci7eXTT" + }, + "user": { + "id": 1, + "username": "admin", + "first_name": "", + "last_name": "" + } + }, + "created": "2017-12-12T16:48:10.489550Z", + "modified": "2017-12-12T16:48:10.522189Z", + "user": 1, + "token": "kqHqxfpHGRRBXLNCOXxT5Zt3tpJogn", + "refresh_token": "miZq3hqSugvYxhzdQYJIBDgIHxJPnT", + "application": 4, + "expires": "2017-12-13T02:48:10.488180Z", + "scope": "read" +} +``` +For an OAuth token, the only fully mutable field is `scope`. The `application` field is *immutable +on update*, and all other fields are totally immutable, and will be auto-populated during creation: +`user` field will be the `user` field of related application; `expires` will be generated according +to Tower configuration setting `OAUTH2_PROVIDER`; `token` and `refresh_token` will be auto-generated +to be non-crashing random strings. + +On RBAC side: +- A user will be able to create a token if they are able to see the related application; +- System admin is able to see and manipulate every token in the system; +- Organization admins will be able to see and manipulate all tokens belonging to Organization + members; +- Other normal users will only be able to see and manipulate their own tokens. +> Note: Users can only see the token or refresh-token _value_ at the time of creation ONLY. + +#### Using OAuth 2 token system as a Personal Access Token (PAT) +The most common usage of OAuth 2 is authenticating users. The `token` field of a token is used +as part of the HTTP authentication header, in the format `Authorization: Bearer <token field value>`. This _Bearer_ +token can be obtained by doing a curl to the `/api/o/token/` endpoint as shown in `api_o_auth_authorization_root_view.md`. + +Here is an example of using that PAT to access an API endpoint using `curl`: +``` +curl -H "Authorization: Bearer kqHqxfpHGRRBXLNCOXxT5Zt3tpJogn" http://localhost:8013/api/v2/credentials/ +``` + +According to OAuth 2 specification, users should be able to acquire, revoke and refresh an access +token. In AWX the equivalent, and the easiest, way of doing that is creating a token, deleting +a token, and deleting a token quickly followed by creating a new one. + +On the other hand, the specification also provides standard ways of doing those. RFC 6749 elaborates +on those topics, but in summary, an OAuth token is officially acquired via authorization using +authorization information provided by applications (special application fields mentioned above). +There are dedicated endpoints for authorization and acquiring tokens. The token acquire endpoint +is also responsible for token refresh, and token revoke is done by a dedicated token revoke endpoint. + +In AWX, our OAuth system is built on top of +[Django Oauth Toolkit](https://django-oauth-toolkit.readthedocs.io/en/latest/), which provides full +support on standard authorization, token revoke and refresh. AWX implements them and puts related +endpoints under `/api/o/` endpoint. Detailed examples on the most typical usage of those endpoints +are available as description text of `/api/o/`. + +#### Token scope mask over RBAC system +The scope of an OAuth token is a space-separated string composed of keywords like 'read' and 'write'. +These keywords are configurable and used to specify permission level of the authenticated API client. +For the initial OAuth implementation, we use the most simple scope configuration, where the only +valid scope keywords are 'read' and 'write'. + +Read and write scopes provide a mask layer over the RBAC permission system of AWX. In specific, a +'write' scope gives the authenticated user full permissions the RBAC system provides, while 'read' +scope gives the authenticated user only read permissions the RBAC system provides. + +For example, if a user has admin permission to a job template, she can both see and modify, launch +and delete the job template if authenticated via session or basic auth. On the other hand, if she +is authenticated using OAuth token, and the related token scope is 'read', she can only see but +not manipulate or launch the job template, despite she has admin role over it; if the token scope is +'write' or 'read write', she can take full advantage of the job template as its admin. + +## Acceptance Criteria +* All CRUD operations for OAuth applications and tokens should function as described. +* RBAC rules applied to OAuth applications and tokens should behave as described. +* A default application should be auto-created for each new user. +* Incoming requests using unexpired OAuth token correctly in authentication header should be able + to successfully authenticate themselves. +* Token scope mask over RBAC should work as described. +* Tower configuration setting `OAUTH2_PROVIDER` should be configurable and function as described. +* `/api/o/` endpoint should work as expected. In specific, all examples given in the description + help text should be working (user following the steps should get expected result). diff --git a/docs/auth/session.md b/docs/auth/session.md index 840cb6160a..ac125caeb4 100644 --- a/docs/auth/session.md +++ b/docs/auth/session.md @@ -1,9 +1,8 @@ ## Introduction ->> Updated to these docs coming soon. -Before Tower 3.3, auth token is used as the main authentication method. Starting from Tower 3.3, -session-based authentication will take the place as the main authentication, while auth token -will be replaced by OAuth tokens also introduced in 3.3. +Before Tower 3.3, auth token was used as the main authentication method. Starting from Tower 3.3, +session-based authentication will take the place as the main authentication method, and auth token +will be replaced by OAuth 2 tokens. Session authentication is a safer way of utilizing HTTP(S) cookies: @@ -11,19 +10,19 @@ Theoretically, user can provide authentication information, like username and pa `Cookie` header, but this method is vulnerable to cookie hijacks, where crackers can see and steal user information from cookie payload. -Session authentication, on the other hand, sets a single `sessionid` cookie, called 'session'. Session +Session authentication, on the other hand, sets a single `session_id` cookie. The session_id is *a random string which will be mapped to user authentication informations by server*. Crackers who -hijacks cookie will only get session itself, which does not imply any critical user info, valid only for +hijacks cookie will only get the session_id itself, which does not imply any critical user info, is valid only for a limited time, and can be revoked at any time. ## Usage -In session authentication, user log in using endpoint `/api/login/`. GET to `/api/login/` displays the +In session authentication, users log in using the `/api/login/` endpoint. A GET to `/api/login/` displays the log in page of API browser: ![Example session log in page](../img/auth_session_1.png?raw=true) -User should enter correct username and password before clicking on 'LOG IN' button, which fires a POST +Users should enter correct username and password before clicking on 'LOG IN' button, which fires a POST to `/api/login/` to actually log the user in. The return code of a successful login is 302, meaning upon successful login, the browser will be redirected, the redirected destination is determined by `next` form item described below. @@ -35,7 +34,7 @@ be provided in the form: * `next`: The path of the redirect destination, in API browser `"/api/"` is used. * `csrfmiddlewaretoken`: The CSRF token, usually populated by using Django template `{% csrf_token %}`. -Session is provided as a return `Set-Cookie` header. Here is a typical one: +The session_id is provided as a return `Set-Cookie` header. Here is a typical one: ``` Set-Cookie: sessionid=lwan8l5ynhrqvps280rg5upp7n3yp6ds; expires=Tue, 21-Nov-2017 16:33:13 GMT; httponly; Max-Age=1209600; Path=/ ``` @@ -45,10 +44,10 @@ session cookie value, expiration date, duration, etc. The duration of the cookie is configurable by Tower Configuration setting `SESSION_COOKIE_AGE` under category `authentication`. It is an integer denoting the number of seconds the session cookie should -live. +live. The default session cookie age is 2 weeks. -After a valid session is acquired, a client should provide session as a cookie for subsequent requests -in order to be authenticated. like +After a valid session is acquired, a client should provide the session_id as a cookie for subsequent requests +in order to be authenticated. For example: ``` Cookie: sessionid=lwan8l5ynhrqvps280rg5upp7n3yp6ds; ... ``` @@ -63,8 +62,7 @@ by performing session acquire with the session provided. A Tower configuration setting, `SESSIONS_PER_USER` under category `authentication`, is used to set the maximum number of valid sessions a user can have at the same time. For example, if `SESSIONS_PER_USER` -is set to 3, while the same user is logged in via 5 different places, and thus have 5 valid sessions -available at the same time, the earliest 2 (5 - 3) sessions created will be invalidated. Tower will try +is set to 3 and the same user is logged in from 5 different places, the earliest 2 sessions created will be invalidated. Tower will try broadcasting, via websocket, to all available clients. The websocket message body will contain a list of invalidated sessions. If a client finds its session in that list, it should try logging out. @@ -79,7 +77,7 @@ is updated, all sessions she owned will be invalidated and deleted. * The maximum number of concurrent login for one user should be configurable by `SESSIONS_PER_USER`, and over-limit user sessions should be warned by websocket. * When a user's password is changed, all her sessions should be invalidated and deleted. -* User should not be able to authenticate either HTTPS(S) request or websocket connect using invalid +* User should not be able to authenticate by HTTPS(S) request nor websocket connect using invalid sessions. * No existing behavior, like job run, inventory update or callback receiver, should be affected by session auth. |