mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-02-20 04:29:24 -06:00
Merge branch 'master' into fix-eos-start
This commit is contained in:
@@ -10,7 +10,7 @@ geekdocFilePath: login-flow.md
|
||||
|
||||
## Login Flow
|
||||
|
||||
The following sequence diagram describes the [openid connect auth flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth):
|
||||
The following sequence diagram describes the [openid connect auth code flow](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth). The eight numbered steps and notes correspond to the [openid connect auth code flow steps](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowSteps). Example requests are based on the spec as well.:
|
||||
|
||||
{{< mermaid class="text-center">}}
|
||||
sequenceDiagram
|
||||
@@ -21,8 +21,7 @@ sequenceDiagram
|
||||
participant user as User
|
||||
participant client as Client
|
||||
participant proxy as ocis-proxy
|
||||
participant idp as external IdP
|
||||
participant konnectd as ocis-konnectd IdP
|
||||
participant idp as IdP
|
||||
participant glauth as ocis-glauth
|
||||
participant graph as ocis-graph
|
||||
participant accounts as ocis-accounts
|
||||
@@ -31,26 +30,33 @@ sequenceDiagram
|
||||
user->>+client: What is the content of my home?
|
||||
|
||||
client->>+proxy: PROPFIND <br> no (or expired) auth
|
||||
alt proxy can decide which idp to use
|
||||
Note over client, idp: We may not be able to differentiate guests from users
|
||||
proxy-->>client: 302 Found
|
||||
Note over client, idp: HTTP/1.1 302 Found<br>Location: https://server.example.com/authorize?<br>response_type=code&<br>scope=openid%20profile%20email<br>&client_id=s6BhdRkqt3<br>&state=af0ifjsldkj<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
else client needs to discover the idp
|
||||
proxy-->>-client: 401 Unauthorized
|
||||
Note over client, idp: Follow OpenID Connect Discovery protocol
|
||||
Note over client, idp: Clients might fall back to the ocis server if the discovery failed.<br>We can provide a webfinger endpoint there to let guests use an idp<br>that is backed bythe accounts service.
|
||||
Note over client, idp: For now, always use ocis well known endpoint to discover idp?<br>We can check the email in the accounts service.
|
||||
end
|
||||
Note over client,proxy: ocis needs to know the IdP that is<br>used to authenticate users. The<br>proxy will redirect unauthenticated<br>requests to that IdP.
|
||||
proxy-->>-client: 302 Found
|
||||
Note over client, idp: HTTP/1.1 302 Found<br>Location: https://server.example.com/authorize?<br>response_type=code&<br>scope=openid%20profile%20email<br>&client_id=s6BhdRkqt3<br>&state=af0ifjsldkj<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
|
||||
Note over client, idp: We should follow the OpenID Connect Discovery protocol
|
||||
Note over client, idp: Clients might fall back to the ocis server if the discovery failed.<br>We can provide a webfinger endpoint there to let guests use an idp<br>that is backed by the accounts service.
|
||||
Note over client, idp: For now, clients can only handle one IdP, which is configured in ocis.
|
||||
|
||||
client-->>client: 1. Client prepares an Authentication Request<br>containing the desired request parameters.
|
||||
|
||||
alt all users authenticated by an external idp
|
||||
client->>+idp: 2. Client sends the request to the Authorization Server.
|
||||
Note over client, idp: GET /authorize?<br>response_type=code<br>&scope=openid%20profile%20email<br>&client_id=s6BhdRkqt3<br>&state=af0ifjsldkj<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1<br>Host: server.example.com
|
||||
Note over user, idp: 3. Authorization Server Authenticates the End-User.
|
||||
client->>+idp: 2. Client sends the request to the Authorization Server.
|
||||
Note over client, idp: GET /authorize?<br>response_type=code<br>&scope=openid%20profile%20email<br>&client_id=s6BhdRkqt3<br>&state=af0ifjsldkj<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1<br>Host: server.example.com
|
||||
Note over user, idp: 3. Authorization Server Authenticates the End-User.
|
||||
Note over idp,ldap: Either an IdP already exists or a new one is introduced. Since we are not yet using oidc discovery we can only use one IdP.
|
||||
alt all users managed by konnectd/ocis
|
||||
idp->>+glauth: LDAP query/bind
|
||||
glauth->>+graph: GET user with Basic Auth<br>GraphAPI
|
||||
graph->>+accounts: internal GRPC
|
||||
accounts-->>-graph: response
|
||||
graph-->>-glauth: OData response
|
||||
glauth-->>-idp: LDAP result
|
||||
Note over accounts,ldap: In case internal users are managed<br>in an external ldap they have to be<br>synced to the accounts service to<br>show up as recipients during sharing.
|
||||
else all users authenticated by an external idp
|
||||
idp->>+ldap: LDAP query/bind
|
||||
ldap-->>-idp: LDAP result
|
||||
alt guest accounts managed in ocis / lookup using glauth proxy:
|
||||
Note over idp,glauth: Idp is configured to use glauth as a<br>second ldap server.
|
||||
idp->>+glauth: LDAP query/bind
|
||||
glauth->>+graph: GET user with Basic Auth<br>GraphAPI
|
||||
graph->>+accounts: internal GRPC
|
||||
@@ -58,38 +64,18 @@ sequenceDiagram
|
||||
graph-->>-glauth: OData response
|
||||
glauth-->>-idp: LDAP result
|
||||
else guest account provisioned by other means
|
||||
Note over idp, ldap: In case guest accounts are stored in an existing ldap they need to be synced to the accounts service to show up as recipients during sharing.
|
||||
Note over accounts, ldap: In case guest accounts are managed<br>in an existing ldap they need to be<br>synced to the accounts service to<br>be able to login and show up as<br>recipients during sharing.
|
||||
end
|
||||
|
||||
Note over user, idp: 4. Authorization Server obtains End-User Consent/Authorization.
|
||||
idp-->>-client: 5. Authorization Server sends the End-User back<br>to the Client with an Authorization Code.
|
||||
Note over client, idp: HTTP/1.1 302 Found<br>Location: https://client.example.org/cb?<br>code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
|
||||
|
||||
client->>+idp: 6. Client requests a response using the<br>Authorization Code at the Token Endpoint.
|
||||
Note over client, idp: POST /token HTTP/1.1<br>Host: server.example.com<br>Content-Type: application/x-www-form-urlencoded<br>grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
idp-->>-client: 7. Client receives a response that contains an<br>ID Token and Access Token in the response body.
|
||||
Note over client, idp: HTTP/1.1 200 OK<br>Content-Type: application/json<br>Cache-Control: no-store<br>Pragma: no-cache<br>{<br>"access_token": "SlAV32hkKG",<br>"token_type": "Bearer",<br>"refresh_token": "8xLOxBtZp8",<br>"expires_in": 3600,<br>"id_token": "a ... b.c ... d.e ... f" // must be a JWT<br>}
|
||||
else all users managed by konnectd/ocis
|
||||
client->>+konnectd: 2. Client sends the request to the Authorization Server.
|
||||
Note over client, konnectd: GET /authorize?<br>response_type=code<br>&scope=openid%20profile%20email<br>&client_id=s6BhdRkqt3<br>&state=af0ifjsldkj<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb HTTP/1.1<br>Host: server.example.com
|
||||
Note over user, konnectd: 3. Authorization Server Authenticates the End-User.
|
||||
konnectd->>+glauth: LDAP query/bind
|
||||
glauth->>+graph: GET user with Basic Auth<br>GraphAPI
|
||||
graph->>+accounts: internal GRPC
|
||||
accounts-->>-graph: response
|
||||
graph-->>-glauth: OData response
|
||||
glauth-->>-konnectd: LDAP result
|
||||
Note over konnectd,ldap: In case the internal users come from an external ldap they have to be synced to the accounts service to show up as recipients during sharing.
|
||||
|
||||
Note over user, konnectd: 4. Authorization Server obtains End-User Consent/Authorization.
|
||||
konnectd-->>-client: 5. Authorization Server sends the End-User back<br>to the Client with an Authorization Code.
|
||||
Note over client, konnectd: HTTP/1.1 302 Found<br>Location: https://client.example.org/cb?<br>code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
|
||||
|
||||
client->>+konnectd: 6. Client requests a response using the<br>Authorization Code at the Token Endpoint.
|
||||
Note over client, konnectd: POST /token HTTP/1.1<br>Host: server.example.com<br>Content-Type: application/x-www-form-urlencoded<br>grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
konnectd-->>-client: 7. Client receives a response that contains an<br>ID Token and Access Token in the response body.
|
||||
Note over client, konnectd: HTTP/1.1 200 OK<br>Content-Type: application/json<br>Cache-Control: no-store<br>Pragma: no-cache<br>{<br>"access_token": "SlAV32hkKG",<br>"token_type": "Bearer",<br>"refresh_token": "8xLOxBtZp8",<br>"expires_in": 3600,<br>"id_token": "a ... b.c ... d.e ... f" // must be a JWT<br>}
|
||||
end
|
||||
Note over user, idp: 4. Authorization Server obtains End-User Consent/Authorization.
|
||||
idp-->>-client: 5. Authorization Server sends the End-User back<br>to the Client with an Authorization Code.
|
||||
Note over client, idp: HTTP/1.1 302 Found<br>Location: https://client.example.org/cb?<br>code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj
|
||||
|
||||
client->>+idp: 6. Client requests a response using the<br>Authorization Code at the Token Endpoint.
|
||||
Note over client, idp: POST /token HTTP/1.1<br>Host: server.example.com<br>Content-Type: application/x-www-form-urlencoded<br>grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA<br>&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
|
||||
idp-->>-client: 7. Client receives a response that contains an<br>ID Token and Access Token in the response body.
|
||||
Note over client, idp: HTTP/1.1 200 OK<br>Content-Type: application/json<br>Cache-Control: no-store<br>Pragma: no-cache<br>{<br>"access_token": "SlAV32hkKG",<br>"token_type": "Bearer",<br>"refresh_token": "8xLOxBtZp8",<br>"expires_in": 3600,<br>"id_token": "a ... b.c ... d.e ... f" // must be a JWT<br>}
|
||||
|
||||
|
||||
client-->>client: 8. Client validates the ID token and<br>retrieves the End-User's Subject Identifier.
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ geekdocFilePath: request-flow.md
|
||||
|
||||
## Request Flow
|
||||
|
||||
The following sequence diagram describes the general request flow:
|
||||
The following sequence diagram describes the general request flow. It shows where account provisioning and token minting are happening:
|
||||
|
||||
{{< mermaid class="text-center">}}
|
||||
sequenceDiagram
|
||||
@@ -25,51 +25,71 @@ sequenceDiagram
|
||||
user->>+client: What is the content of my home?
|
||||
|
||||
client->>+proxy: PROPFIND <br> Bearer auth using oidc auth token
|
||||
Note right of client: What is in a bearer token? <br> The spec recommends opaque tokens. <br> So it is just random byte noise.
|
||||
Note over client,proxy: What is in a bearer token? <br> The spec recommends opaque tokens. <br> Treat it as random byte noise.
|
||||
Note over client,proxy: the proxy MUST authenticate users <br> using ocis-accounts because it needs <br> to decide where to send the request
|
||||
%% Mention introspection endpoint for opaque tokens
|
||||
%% konnectd uses jwt, so we can save a request
|
||||
%% either way the token can be used to look up the sub and iss of the user
|
||||
|
||||
%% or is token check enough?
|
||||
proxy->>+idp: GET /userinfo
|
||||
idp-->>-proxy: JSON response
|
||||
Note right of proxy: the result contains <br> the sub of the user
|
||||
%% see: https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
||||
alt userinfo succeeds
|
||||
|
||||
proxy->>+accounts: TODO API call to exchange sub@iss with account UUID
|
||||
idp-->>proxy: 200 OK
|
||||
Note over proxy,accounts: Content-Type: application/json<br>{<br>"sub": "248289761001",<br>"name": "Jane Doe",<br>"given_name": "Jane",<br>"family_name": "Doe",<br>"preferred_username": "j.doe",<br>"email": "janedoe@example.com",<br>"picture": "http://example.com/janedoe/me.jpg"<br>}
|
||||
%% see: https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse
|
||||
|
||||
alt internal account
|
||||
accounts->>+ldap: is user allowed to use ocis
|
||||
ldap-->>-accounts: yes/no - group based
|
||||
else guest account
|
||||
accounts->>accounts: check if is valid guest account
|
||||
end
|
||||
else userinfo fails
|
||||
|
||||
idp-->>-proxy: 401 Unauthorized
|
||||
Note over proxy,accounts: WWW-Authenticate: error="invalid_token",<br>error_description="The Access Token expired"
|
||||
|
||||
accounts-->>-proxy: new or existing account UUID / error
|
||||
Note right of accounts: actually this provisions <br> the account including <br> displayname, email and <br> sub@iss if the user is <br> allowed to login, based <br> on group membership <br> in the ldap server
|
||||
|
||||
|
||||
Note right of proxy: the proxy MUST <br> authenticate users <br> using ocis-accounts <br> because it needs to <br> decide where to <br> send the request
|
||||
|
||||
Note right of proxy: forward request to <br> ocis or oc10
|
||||
%% what if oc10 does not support a certain request / API
|
||||
alt user is migrated
|
||||
|
||||
Note right of proxy: mint an internal jwt <br> token that includes <br> the UUID and username
|
||||
proxy->>+reva: PROPFIND <br> Bearer auth using internal JWT
|
||||
reva-->>-proxy: Multistatus response
|
||||
|
||||
else user is not migrated
|
||||
|
||||
Note right of proxy: forward existing bearer auth?
|
||||
proxy->>+oc10: PROPFIND <br> Bearer auth using internal JWT
|
||||
%% TODO auth using internal token?
|
||||
oc10-->>-proxy: Multistatus response
|
||||
proxy-->>client: 401 Unauthorized or <br>302 Found with redirect to idp
|
||||
Note over client: start at login flow<br> or refresh the token
|
||||
|
||||
end
|
||||
|
||||
proxy->>+accounts: TODO API call to exchange sub@iss with account UUID
|
||||
Note over proxy,accounts: does not autoprovision users. They are explicitly provsioned later.
|
||||
|
||||
alt account exists or has been migrated
|
||||
|
||||
accounts-->>proxy: existing account UUID
|
||||
else account does not exist
|
||||
|
||||
opt oc10 endpoint is configured
|
||||
Note over proxy,oc10: Check if user exists in oc10
|
||||
proxy->>+oc10: GET /apps/graphapi/v1.0/users/<uuid>
|
||||
opt user exists in oc10
|
||||
oc10-->>-proxy: 200
|
||||
%% TODO auth using internal token
|
||||
proxy->>+oc10: PROPFIND
|
||||
Note over proxy,oc10: forward existing bearer auth
|
||||
oc10-->>-proxy: Multistatus response
|
||||
proxy-->>client: Multistatus response
|
||||
client-->>user: List of Files X, Y, Z ...
|
||||
end
|
||||
end
|
||||
|
||||
Note over proxy,accounts: provision a new account including displayname, email and sub@iss <br> TODO only if the user is allowed to login, based on group <br> membership in the ldap server
|
||||
proxy->>proxy: generate new uuid
|
||||
proxy->>+accounts: TODO create account with new generated uuid
|
||||
accounts-->>-proxy: OK / error
|
||||
|
||||
else account has been disabled
|
||||
|
||||
accounts-->>-proxy: account is disabled
|
||||
proxy-->>client: 401 Unauthorized or <br>302 Found with redirect to idp
|
||||
Note over client: start at login flow<br> or refresh the token
|
||||
|
||||
end
|
||||
proxy->>proxy: store uuid in context
|
||||
|
||||
%% what if oc10 does not support a certain request / API
|
||||
|
||||
proxy->>proxy: mint an internal jwt that includes the UUID and username using revas `x-access-token` header
|
||||
proxy->>+reva: PROPFIND <br>Token auth using internal JWT
|
||||
reva-->>-proxy: Multistatus response
|
||||
proxy-->>-client: Multistatus response
|
||||
|
||||
client-->>-user: List of Files X, Y, Z ...
|
||||
|
||||
Reference in New Issue
Block a user