Skip to content

Commit

Permalink
refactor: rename login request to login flow
Browse files Browse the repository at this point in the history
As part of this change, fetching a login flow over the public API no longer requires Anti-CSRF cookies to be sent.

Partially closes #635

BREAKING CHANGE: Wording has changed from "Self-Service Login Request" to "Self-Service Login Flow" to follow community feedback and practice already applied in the documentation. Additionally, fetching a login flow over the public API no longer requires Anti-CSRF cookies to be sent.

This patch renames several important login flow endpoints:

- `/self-service/browser/flows/login` is now `/self-service/login/browser` without functional changes.
- `/self-service/browser/flows/requests/login?request=abcd` is now `/self-service/login/flows?id=abcd` and no longer needs anti-CSRF cookies to be available.

Additionally, the URL for completing the password and oidc login method has been moved. Given that this endpoint is typically not manually called, you can probably ignore this change:

- `/self-service/browser/flows/login/strategies/password?request=abcd` is now `/self-service/login/methods/password?flow=abcd` without functional changes.
- `/self-service/browser/flows/strategies/oidc?request=abcd` is now `/self-service/methods/oidc?flow=abcd` without functional changes.

The Login UI Endpoint no longer receives a `?request=abcde` query parameter but instead a `?flow=abcde` query parameter. Functionality did not change however.

As part of this change SDK methods have been renamed:

```
  const kratos = new CommonApi(config.kratos.public)
  // ...
- kratos.getSelfServiceBrowserLoginRequest(req.query.request)
+ kratos.getSelfServiceLoginFlow(req.query.flow)
```

This patch requires you to run SQL migrations.
  • Loading branch information
aeneasr committed Aug 25, 2020
1 parent 79ed63c commit 9369d1b
Show file tree
Hide file tree
Showing 83 changed files with 2,184 additions and 1,977 deletions.
635 changes: 190 additions & 445 deletions .schema/api.swagger.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions cmd/daemon/serve.go
Expand Up @@ -128,8 +128,8 @@ func sqa(cmd *cobra.Command, d driver.Driver) *metricsx.Service {
password.RegistrationPath,
password.LoginPath,
oidc.BasePath,
login.BrowserInitPath,
login.BrowserRequestsPath,
login.RouteInitBrowserFlow,
login.RouteGetFlow,
logout.BrowserLogoutPath,
registration.BrowserRegistrationPath,
registration.BrowserRegistrationRequestsPath,
Expand Down
70 changes: 35 additions & 35 deletions docs/docs/self-service/flows/user-login-user-registration.mdx
Expand Up @@ -82,11 +82,11 @@ you reference these routes in your ORY Kratos config file:
urls:
login_ui: https://.../login
registration_ui: https://.../registration

# ...
```

Depending on the type of login flows you want to support, you may a also add a
Depending on the type of login flows you want to support, you may also add a
"Sign up/in with GitHub" flow:

```html
Expand All @@ -104,7 +104,7 @@ HTML. Instead, you need to implement the HTML code in your application (e.g.
NodeJS + ExpressJS, Java, PHP, ReactJS, ...), which gives you extreme
flexibility and customizability in your user interface flows and designs.

Each Login and Registration Strategy (e.g.
Each Login and Registration Method (e.g.
[Username and Password](user-login-user-registration/username-email-password.mdx),
[Social Sign In](user-login-user-registration/openid-connect-social-sign-in-oauth2.mdx),
Passwordless, ...) works a bit different but they all boil down to the same
Expand All @@ -116,10 +116,10 @@ sequenceDiagram
participant B as Browser
participant K as ORY Kratos
participant A as Your Application
B->>K: Initiate Login
K->>B: Redirects to your Application's /login endpoint
B->>A: Calls /login
A-->>K: Fetches data to render forms etc
B->>K: Initiate Login Flow
K->>B: Redirects to your Application's /login?flow=<flow-id> endpoint
B->>A: Calls /login?flow=<flow-id>
A-->>K: Fetches data to render forms using ?flow=<flow-id>
B-->>A: Fills out forms, clicks e.g. "Submit Login"
B->>K: POSTs data to
K-->>K: Processes Login Info
Expand All @@ -137,7 +137,7 @@ sequenceDiagram
/>

The exact data being fetched and the step _"Processes Login / Registration
Info"_ depend, of course, on the actual Strategy being used. But it is important
Info"_ depend, of course, on the actual Login / Registration Method being used. But it is important
to understand that **"Your Application"** is responsible for rendering the
actual Login and Registration HTML Forms. You can of course implement one app
for rendering all the Login, Registration, ... screens, and another app (think
Expand Down Expand Up @@ -196,22 +196,22 @@ const adminEndpoint = new AdminApi('https://ory-kratos-admin.example-org.vpc/')
export const authHandler = (flow) => (req, res, next) => {
// The request ID is used to identify the login and registraion request and
// return data like the csrf_token and so on.
const request = req.query.request
if (!request) {
const flowId = req.query.flow
if (!flowId) {
console.log(`No request found in URL, initializing ${flow} flow.`)
res.redirect(`${kratosBrowserUrl}/self-service/browser/${flow}`)
res.redirect(`${kratosBrowserUrl}/self-service/${flow}/browser`)
return
}

const authRequest =
type === 'login'
? adminEndpoint.getSelfServiceBrowserLoginRequest(request)
: adminEndpoint.getSelfServiceBrowserRegistrationRequest(request)
flow === 'login'
? adminEndpoint.getSelfServiceLoginFlow(flowId)
: adminEndpoint.getSelfServiceRegistrationFlow(flowId)

authRequest.then(({ body, response }) => {
if (response.statusCode !== 200) {
res.redirect(
`${config.kratos.browser}/self-service/browser/flows/${type}`
`${config.kratos.browser}/self-service/browser/flows/${flow}`
)
return
}
Expand Down Expand Up @@ -342,9 +342,9 @@ summarized in this state diagram:
stateDiagram
s1: User browses app
s2: Execute "Before Login/Registration Hook(s)"
s3: User Interface Application renders "Login/Registration Request"
s3: User Interface Application renders "Login/Registration Flow"
s4: Execute "After Login/Registration Hook(s)"
s5: Update "Login/Registration Request" with Error Context(s)
s5: Update "Login/Registration Flow" with Error Context(s)
s6: Login/Registration successful
[*] --> s1
s1 --> s2 : User clicks "Log in / Sign up"
Expand All @@ -367,7 +367,7 @@ stateDiagram
1. The user's browser is redirected to
`http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/(login|registration)`
(the notation `(login|registration)` expresses the two possibilities of
`../self-service/browser/flows/login` or
`../self-service/login/browser` or
`../self-service/browser/flows/registration`).
1. ORY Kratos does some internal processing (e.g. checks if a session cookie is
set, generates payloads for form fields, sets CSRF token, ...) and redirects
Expand All @@ -378,11 +378,11 @@ stateDiagram
to the ui endpoints - for example `https://127.0.0.1:4455/auth/login` and
`https://127.0.0.1:4455/auth/registration`). The user's browser is thus
redirected to
`https://127.0.0.1:4455/auth/(login|registration)?request=abcde`. The
`https://127.0.0.1:4455/auth/(login|registration)?flow=abcde`. The
`request` query parameter includes a unique ID which will be used to fetch
contextual data for this login request.
1. Your Server-Side Application makes a `GET` request to
`http://kratos:4434/self-service/browser/flows/requests/(login|registration)?request=abcde`.
`http://kratos:4434/self-service/browser/flows/requests/(login|registration)?flow=abcde`.
ORY Kratos responds with a JSON Payload that contains data (form fields,
error messages, ...) for all enabled User Login Strategies:
```json5
Expand Down Expand Up @@ -434,9 +434,9 @@ stateDiagram
}
```
and the user's Browser is redirected back to the Login UI:
`https://127.0.0.1:4455/auth/(login|registration)?request=abcde`.
`https://127.0.0.1:4455/auth/(login|registration)?flow=abcde`.
- If credentials / data is valid, ORY Kratos proceeds with the next step.
- If the flow is a registration request and the registration data is valid,
- If the flow is a registration flow and the registration data is valid,
the identity is created.
1. ORY Kratos executes hooks defined in the **After Login/Registration Hooks**.
If a failure occurs, the whole flow is aborted.
Expand All @@ -453,13 +453,13 @@ sequenceDiagram
participant KP as ORY Kratos Public API
participant KA as ORY Kratos Admin API
B->>+A: GET /.ory/kratos/public/self-service/browser/flows/(login|registration)
A->>+KP: GET /self-service/browser/flows/login(login|registration)
A->>+KP: GET /self-service/login/browser(login|registration)
KP-->>KP: Execute Hooks defined in "Before Login/Registration"
KP-->>-A: HTTP 302 Found /auth/(login|registration)?request=abcde
A-->>-B: HTTP 302 Found /auth/(login|registration)?request=abcde
B->>+A: GET /auth/(login|registration)?request=abcde
A->>+KA: GET/self-service/browser/flows/requests/(login|registration)?request=abcde
KA->>-A: Sends Login/Registration Request JSON Payload
KP-->>-A: HTTP 302 Found /auth/(login|registration)?flow=abcde
A-->>-B: HTTP 302 Found /auth/(login|registration)?flow=abcde
B->>+A: GET /auth/(login|registration)?flow=abcde
A->>+KA: GET/self-service/browser/(login|registration)/flows?id=abcde
KA->>-A: Sends Login/Registration Flow JSON Payload
Note over A,KA: {"methods":{"password":...,"oidc":..}}
A-->>A: Generate and render HTML
A-->>-B: Return HTML (Form, ...)
Expand All @@ -475,7 +475,7 @@ sequenceDiagram
A->>-B: Send Dashboard Response
else Login data is invalid
Note over KP,B: User retries login / registration
KP-->>B: HTTP 302 Found /auth/(login|registration)?request=abcde
KP-->>B: HTTP 302 Found /auth/(login|registration)?flow=abcde
end
`}
/>
Expand All @@ -486,20 +486,20 @@ Because Client-Side Browser Applications do not have access to ORY Kratos' Admin
API, they must use the ORY Kratos Public API instead. The flow for a Client-Side
Browser Application is almost the exact same as the one for Server-Side
Applications, with the small difference that
`https://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/requests/login?request=abcde`
`https://127.0.0.1:4455/.ory/kratos/public/self-service/login/flows?id=abcde`
would be called via AJAX instead of making a request to
`https://kratos:4434/self-service/browser/flows/requests/login?request=abcde`.
`https://kratos:4434/self-service/login/flows?id=abcde`.

To prevent brute force, guessing, session injection, and other attacks, it is
required that cookies are working for this endpoint. The cookie set in the
initial HTTP request made to
`https://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/login`
`https://127.0.0.1:4455/.ory/kratos/public/self-service/login/browser`
MUST be set and available when calling this endpoint!

:::info

The initialization request
(`http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/(login|registration)`)
(`http://127.0.0.1:4455/.ory/kratos/public/self-service/(login|registration)/browser`)
**cannot** be made via AJAX or API requests. You **must** open that URL in the
user's browser using e.g. `window.open` `location.href` or plain and simple old
`<a href=...>`.
Expand Down Expand Up @@ -532,5 +532,5 @@ Refreshing a session will not log the user out, unless another user signs in.
:::

To refresh a session, append `?refresh=true` to
`/self-service/browser/flows/login`, for example
`http://127.0.0.1:4455/.ory/kratos/public/self-service/browser/flows/login?refresh=true`.
`/self-service/login/browser`, for example
`http://127.0.0.1:4455/.ory/kratos/public/self-service/login/browser?refresh=true`.
4 changes: 2 additions & 2 deletions go.mod
Expand Up @@ -22,11 +22,11 @@ require (
github.com/go-playground/locales v0.12.1 // indirect
github.com/go-playground/universal-translator v0.16.0 // indirect
github.com/go-swagger/go-swagger v0.25.0
github.com/gobuffalo/fizz v1.11.0
github.com/gobuffalo/fizz v1.11.1-0.20200706214517-4e9fb9ced4ce
github.com/gobuffalo/httptest v1.0.2
github.com/gobuffalo/logger v1.0.3
github.com/gobuffalo/packr/v2 v2.8.0
github.com/gobuffalo/pop/v5 v5.2.4-0.20200707154617-81b8a32a605f
github.com/gobuffalo/pop/v5 v5.2.4-0.20200706214017-1dd950510b30
github.com/gobuffalo/uuid v2.0.5+incompatible
github.com/gofrs/uuid v3.2.0+incompatible
github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Expand Up @@ -350,6 +350,8 @@ github.com/gobuffalo/fizz v1.9.8/go.mod h1:w1FEn1yKNVCc49KnADGyYGRPH7jFON3ak4Bj1
github.com/gobuffalo/fizz v1.10.0/go.mod h1:J2XGPO0AfJ1zKw7+2BA+6FEGAkyEsdCOLvN93WCT2WI=
github.com/gobuffalo/fizz v1.11.0 h1:kJ+9sSSZpolHz4ULV1sF76AGmo74kEi6IztIc4HmshU=
github.com/gobuffalo/fizz v1.11.0/go.mod h1:cXLjhE5p3iuIes6AGZ/9+dfyOkehlB2Vldj0Iw2Uu38=
github.com/gobuffalo/fizz v1.11.1-0.20200706214517-4e9fb9ced4ce h1:Y0QAYLDJp9VJUOefsaHZFEDSILz6nRKZxcToDhcSKZY=
github.com/gobuffalo/fizz v1.11.1-0.20200706214517-4e9fb9ced4ce/go.mod h1:cXLjhE5p3iuIes6AGZ/9+dfyOkehlB2Vldj0Iw2Uu38=
github.com/gobuffalo/flect v0.0.0-20180907193754-dc14d8acaf9f/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
github.com/gobuffalo/flect v0.0.0-20181002182613-4571df4b1daf/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
github.com/gobuffalo/flect v0.0.0-20181007231023-ae7ed6bfe683/go.mod h1:rCiQgmAE4axgBNl3jZWzS5rETRYTGOsrixTRaCPzNdA=
Expand Down Expand Up @@ -547,8 +549,8 @@ github.com/gobuffalo/pop v4.13.1+incompatible h1:AhbqPxNOBN/DBb2DBaiBqzOXIBQXxEY
github.com/gobuffalo/pop v4.13.1+incompatible/go.mod h1:DwBz3SD5SsHpTZiTubcsFWcVDpJWGsxjVjMPnkiThWg=
github.com/gobuffalo/pop/v5 v5.0.11/go.mod h1:mZJHJbA3cy2V18abXYuVop2ldEJ8UZ2DK6qOekC5u5g=
github.com/gobuffalo/pop/v5 v5.2.0/go.mod h1:Hj586Cr7FoTFNmvzyNdUcajv3r0A+W+bkil4RIX/zKo=
github.com/gobuffalo/pop/v5 v5.2.4-0.20200707154617-81b8a32a605f h1:YtZ18YgopG9edqCaGaqDlGjd7WdWusyDcNWIhf+Sj5k=
github.com/gobuffalo/pop/v5 v5.2.4-0.20200707154617-81b8a32a605f/go.mod h1:4mYDlrcXTnG2n9rG8p+c10X1QnfMc4YIRVmiC8ihMAI=
github.com/gobuffalo/pop/v5 v5.2.4-0.20200706214017-1dd950510b30 h1:X/MkpfklOlyXqudnUMX01xSXTxtVaq9aEc/aCFN+0TY=
github.com/gobuffalo/pop/v5 v5.2.4-0.20200706214017-1dd950510b30/go.mod h1:4mYDlrcXTnG2n9rG8p+c10X1QnfMc4YIRVmiC8ihMAI=
github.com/gobuffalo/release v1.0.35/go.mod h1:VtHFAKs61vO3wboCec5xr9JPTjYyWYcvaM3lclkc4x4=
github.com/gobuffalo/release v1.0.38/go.mod h1:VtHFAKs61vO3wboCec5xr9JPTjYyWYcvaM3lclkc4x4=
github.com/gobuffalo/release v1.0.42/go.mod h1:RPs7EtafH4oylgetOJpGP0yCZZUiO4vqHfTHJjSdpug=
Expand Down
8 changes: 4 additions & 4 deletions internal/faker.go
Expand Up @@ -81,16 +81,16 @@ func RegisterFakes() {
panic(err)
}

if err := faker.AddProvider("login_request_methods", func(v reflect.Value) (interface{}, error) {
var methods = make(map[identity.CredentialsType]*login.RequestMethod)
if err := faker.AddProvider("login_flow_methods", func(v reflect.Value) (interface{}, error) {
var methods = make(map[identity.CredentialsType]*login.FlowMethod)
for _, ct := range []identity.CredentialsType{identity.CredentialsTypePassword, identity.CredentialsTypeOIDC} {
var f form.HTMLForm
if err := faker.FakeData(&f); err != nil {
return nil, err
}
methods[ct] = &login.RequestMethod{
methods[ct] = &login.FlowMethod{
Method: ct,
Config: &login.RequestMethodConfig{RequestMethodConfigurator: &f},
Config: &login.FlowMethodConfig{FlowMethodConfigurator: &f},
}

}
Expand Down

0 comments on commit 9369d1b

Please sign in to comment.