From 42cd2442e1f5703ec5231e320076bce376e175c1 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 19 Sep 2020 12:50:53 +0300 Subject: start over from the beginning --- yuck.bib | 7 ++ yuck.md | 425 ++++++--------------------------------------------------------- 2 files changed, 42 insertions(+), 390 deletions(-) create mode 100644 yuck.bib diff --git a/yuck.bib b/yuck.bib new file mode 100644 index 0000000..c39c0d7 --- /dev/null +++ b/yuck.bib @@ -0,0 +1,7 @@ +@manual{rfc8252, +title = "OAuth 2.0 for Native Apps", +author = "W. Denniss and J. Bradley", +organization = "IETF", +year = 2017, +month = October, +} diff --git a/yuck.md b/yuck.md index 704eb83..edaf804 100644 --- a/yuck.md +++ b/yuck.md @@ -1,16 +1,21 @@ # Overview -Yuck may some day become an OpenID Connect and OAuth server. This is -just a sketcth for what it might look like. +This a description of two authentication and authorization protocols, +and a sketch of acceptance criteria for an implementation of them. + +This is very much work in progress. + ## Concepts Some basic concepts in this document: -* identity: data about who you are to tell you apart from everyone - else -* authentication: proving your identity -* authorization: giving permission to do something +* **identity** – data about who you are to tell you apart from + everyone else +* **authentication** – proving your identity +* **authorization** – giving you permission to do something + +FIXME: These could do with citations. ## The protocols: OAuth and OpenID Connect @@ -30,413 +35,53 @@ identity provider can keep a login session open independently of the other services and applications, this provides a single sign-on experience. +FIXME: add examples of what each protocol is suited for. + +We discuss here only these specific versions of these protocols, and +even then only subsets chosen based mainly from the point of security. ## Entities involved in the protocols The protocols involves the following entities: -* the **end user**, who is trying to do something; also the resource - owner +* the **end user**, who is trying to do something; also known as the + resource owner * the **web browser**, used by the user; might be a mobile or command - line application instead of a browser per se + line application instead of a browser as such; also know as the user + agent * the **application**, which the user uses to do things, and as part - of that access resources + of that access resources; also know as the requesting party and the + facade * the **resource provider**, where the resources are, and which allows access to them via a web API * the **identity provider** (IDP), which authenticates the user -# The protocols - - -Yuck only supports specific versions and subsets of the protocols it -implements, chosen based mainly from the point of security. FIXME: -expand this with explanations of why the specific choices have been -made and why other subsets (grants, flows) are not chosen. - -## The OAuth 2.0 protocol: client credentials grant - -See [RFC8252][] for a description of the client credentials grant. - -[RFC8252]: https://tools.ietf.org/html/rfc8252 - -## The OIDC 1.0 protocol: authorization code - -This augments the plain OIDC with cookies: - -* an **app cookie** set by the application to tie a user and their - session together: this lets the application store data about the - user and what they're doing between HTTP requests -* a **login cookie** set by the IDP to remember this user has a valid - login session - - -### Successful resource access by a logged-out user - -~~~plantuml -@startuml - -actor "End user" as user -participant browser as "User agent \n (web browser)" -participant app as "Application \n (web, mobile)" -participant idp as "Identity provider" -database rp as "Resource provider" - -user -> browser : clicks on something -note left - User initiates an action - that requires a protected - resource from the - resource provider. -endnote - -browser -> app : GET /something -note left - Browser asks the - application for what - the user asked for. -end note - -browser <- app : redirect to IDP /login?... -note right - Application does not have - a session open for user. - It redirects browser to - IDP for login and sets - an **app cookie**. It - remember what resource - the user was asking for. -end note - -browser -> idp : GET /login?... -note left - Browser follows redirect. - The URL contains the application's - client id, callback URL, and other - information the IDP will need later. -end note - -browser <- idp: login page -note right - IDP has no login session for - user (no **login cookie**). - It creates an internal - authentication process - record. -end note - -user <- browser : show login form - -user -> browser : enter login info - -browser -> idp : POST login form -note left - URL includes identifier - for authentication record. -end note - -browser <- idp : redirect to app /callback?code=... -note right - IDP checks credentials, - generates **authorization code**, - stores it in the authentication - process record and in the - redirect URL. - - IDP sets **login cookie**. -end note - -browser -> app : GET /callback?code=... -note left - Browser follows redirect, - includes **app cookie**. -end note - -app -> idp : request tokens using authz code -note left - Application gets access, - id, and refresh tokens from - IDP, using the **authorization code** - it just got. - - Application uses Basic Auth - to prove which application it is. -end note - -app <- idp : access, id, and refresh tokens -note right - IDP checks applicaion - credential and generates - the tokens. - - IDP forgets the code - (it's single-use only). -end note -note left - Application stores the - cookies so they can - be found via the - **app cookie**. -end note - -app -> rp : access resource with access token -note left - Application gets the resource - the user originally asked for. - It remembers what it was thank - so the **app cookie**. -end note - -app <- rp : resource - -browser <- app : page with resource - -user <- browser : show what the user wanted - -@enduml -~~~ - -### Successful resource access by a logged-in user - -~~~plantuml -@startuml - -actor "End user" as user -participant browser as "User agent \n (web browser)" -participant app as "Application \n (web, mobile)" -participant idp as "Identity provider" -database rp as "Resource provider" - -user -> browser : clicks on something -note left - User initiates an action - that requires a protected - resource from the - resource provider. -endnote - -browser -> app : GET /something -note left - Browser asks the - application for what - the user asked for. - - The **app cookie** is - included in the request. -end note - -app -> rp : access resource with access token -note left - Application gets the resource - using the **access token** it - has associated with the - **app cookie**. -end note - -app <- rp : resource - -browser <- app : page with resource - -user <- browser : show what the user wanted - -@enduml -~~~ - - -### Successful request when an access cookie has expired - -~~~plantuml -@startuml - -actor "End user" as user -participant browser as "User agent \n (web browser)" -participant app as "Application \n (web, mobile)" -participant idp as "Identity provider" -database rp as "Resource provider" - -user -> browser : clicks on something -note left - User initiates an action - that requires a protected - resource from the - resource provider. -endnote - -browser -> app : GET /something -note left - Browser asks the - application for what - the user asked for. - - The **app cookie** is - included in the request. -end note - -app -> rp : access resource with access token -note left - Application gets the resource - using the **access token** it - has associated with the - **app cookie**. -end note - -app <- rp : access denied -note right - The RP sees the **access token** - is expired and returns an - error. -end note - -app -> idp : request new access cookie -note left - Application uses the - **refresh token** to get - a **new access token**. -end note - -app <- idp : new access token -note left - Application stores - **new access token** in - user's session. -end note - -app -> rp : access resource with new access token -note left - Application gets the resource - using the **new access token**. -end note - -app <- rp : resource - -browser <- app : page with resource - -user <- browser : show what the user wanted - -@enduml -~~~ - - -### FIXME: unhappy paths -# Acceptance criteria - -This chapter captures the acceptance criteria for Yuck in the form of -*scenarios* using the Subplot language. Subplot allows Yuck to be -automatically verified against the criteria. - -## Server reports its version - -~~~scenario -given a running Yuck at https://auth.example.com -when I do GET /version without a token -then response status code is 200 -~~~ - -## OAuth2 client credentials grant - -An example request: - -~~~ -POST /token HTTP/1.1 -Authorization: Basic USERPASS -Content-Type: application/x-www-form-urlencoded - -grant_type=client_credentials&scope=foo+bar+foobar -~~~ - -The `USERPASS` has the client id and secret encoded as is usual for -[HTTP Basic authentication][]. - -[HTTP Basic authentication]: https://en.wikipedia.org/wiki/Basic_access_authentication - -Yuck checks the client id and secret against known, pre-registered -clients, and that the `grant_type` URL parameter is -`client_credential`, and returns a signed JWT access token, if all is -OK. - -~~~json -{ - "iss": "https://auth.example.com", - "sub": "", - "aud": "CLIENT_ID", - "exp": 123456, - "scope": "foo bar" -} -~~~ - -The fields are as follows: - -* `sub` is empty, because this interaction involves not end-user or - subject -* `iss` is the configured URL from the Yuck configuration -* `aud` is the requesting client id -* `exp` is the timestamp in Unix seconds when the token stops being - valid -* `scope` is the space-delimieted list of scopes the client is allowed - to have and has requested - -### Get token with OAuth using client credentials - -~~~scenario -given a running Yuck at https://auth.example.com -and I am a registered OAuth client -and I am authorized to have scope foo -when I do POST /token with grant_type=client_credential&scope=foo+bar -then response status code is 200 -and response has header content-type: application/json -and response body is a valid, signed JWT token -and token sub is empty -and token has iss: "https://auth.example.com" -and token has aud set to my client id -and token expires at least 60 seconds in the future -and token has scope: "foo" -~~~ - - -### End-user interactive login +FIXME: references for these -This is a bit long. +# The OAuth 2.0 protocol: client credentials grant -~~~scenario -given a running Yuck at https://auth.example.com -and I am registered as tomjon with password hunter2 -and I am authorized to have scope foo -and the application is registered at https://app.example.com -when I go to the application login page -then response status code is 302 -and response has header Location: https://auth.example.com/auth?response_type=code&scope=openid+foo&client_id=facade&state=RANDOM&redirect_uri=https://app.example.com/callback +FIXME: give a very high level overview of the protocol, and what +grants are -when I follow the redirect -then response status code is 200 -and response has header content-type: text/html -and body HTML form has username -and body HTML form has password +FIXME: reference some other sources of information -when I do POST /auth with username=tomjon&password=wrong -then response status code is 401 +FIXME: explain why only this grant is chosen -when I do POST /auth with username=tomjon&password=hunter2 -then response status code is 302 -and response has header Location: https://app.example.com/callback?... -and I remember the Location URL code parameter +See [@rfc8252] for a description of the client credentials grant. -when I follow the redirect -when the application requests a token using remembered code -then response status code is 200 -and response has header content-type: application/json -and body has field access_token -and body has field token_type: Bearer -and body has field expires_in -and access_token is a valid, signed JWT -and access_token has scope: "foo" -and access_token has sub: "tomjon" -~~~ +# The OIDC 1.0 protocol: authorization code +FIXME: write this +# References --- -title: Yuck or OIDC +title: "OAuth2 and OpenID Connect: protocols and acceptance criteria" +author: Lars Wirzenius +documentclass: report +bibliography: yuck.bib bindings: - yuck.yaml classes: -- cgit v1.2.1