Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auth Docs #73

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
67 changes: 67 additions & 0 deletions docs/OIDC_sequence_diagram.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# https://infosec.mozilla.org/guidelines/iam/openid_connect.html
# https://github.com/mozilla/infosec.mozilla.org/blob/master/docs/guidelines/assets/images/OIDC_sequence_diagram.txt

# This file can be used with https://sequencediagram.org/
# And rendered to an image file

title Authentication Sequence with OpenID Connect

participant "User's Browser (User-Agent)" as UserAgent
participant "Website (Relying Party)" as RP
participant "OIDC Provider (OP)" as OP
participant "LDAP, GitHub, etc. (IdP)" as IdP


note over UserAgent: User visits https:\/\/rp.example.net
UserAgent->RP: GET https:\/\/rp.example.net/
RP->OP: GET https:\/\/op.example.net/.well-known/openid-configuration
OP->RP: JSON meta-data document

note left of OP:JSON meta-data document:\n{"token_endpoint": "https:\/\/op.example.net/oauth/token", \n"authorization_endpoint":"https:\/\/op.example.net/authorize?...",\n[...]}

RP->UserAgent: 302 Redirect to https:\/\/op.example.net/authorize?[...]

note left of RP:GET /authorize parameters:\nstate=xxx (CSRF protection)\nnonce=xxx (server-side replay protection)\nscope=openid email profile\nredirect_uri=https:\/\/rp.example.net/callback (OP will redirect here)\nresponse_type=code\nclient_id=xxx (RP identifier)


UserAgent->OP: GET https:\/\/op.example.net/authorize?[...]
OP->UserAgent: Show hosted login page
UserAgent->OP: Performs login
OP->IdP: authenticate user (via OIDC or other means)
IdP->OP: return user attributes
OP->UserAgent: 302 Redirect to https:\/\/rp.example.net/callback?[...] (redirect_uri)

note left of RP:GET /callback parameters:\nstate=xxx\ncode=xxx

UserAgent->RP: GET https:\/\/rp.example.net/callback?[...]
RP->OP: POST https:\/\/op.example.net/oauth/token

note right of RP:POST /oauth/token parameters:\nclient_id=xxx\nclient_secret=xxx (secret identifying the RP to the OP)\ngrant_type=authorization_code\ncode=xxx\nstate=xxx


OP->RP: JSON {"base64(id_token)", "access_token", ...}

note right of RP:JSON Document:\n{\n\n "id_token": ADNqVMtqKeYp5w==...,\n "access_token": xxx,\n "email": "test@rp.example.net,\n "attribute1": ...,\n "attribute2": ...,\n [...]\n}

RP->RP: Verify id_token signature is valid, signed by OP


RP->UserAgent: 302 Redirect https:\/\/rp.example.net/
note over UserAgent: User is authenticated to https:\/\/rp.example.net
UserAgent->RP: GET https:\/\/rp.example.net/
RP->UserAgent: rp.example.net's page is displayed

== 15 minutes later... (session require refresh) ==



UserAgent->RP: GET https:\/\/rp.example.net/
RP->UserAgent: 302 Redirect to https:\/\/op.example.net/authorize?**prompt=none**[...]

UserAgent->OP: GET https:\/\/op.example.net/authorize?**prompt=none**[...]
OP->IdP: silently re-authenticate user
IdP->OP: return new/current user attributes
OP->UserAgent: 302 Redirect to https:\/\/rp.example.net/callback?[...] (redirect_uri)

note over UserAgent: User session, expiration and profile attributes are refreshed
RP->UserAgent: rp.example.net's page is displayed
48 changes: 48 additions & 0 deletions docs/femr_OIDC_sequence_diagram.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# This file can be used with https://sequencediagram.org/
# And rendered to an image file

title fEMR Authentication Sequence with OpenID Connect

participant "User's Browser (User-Agent)" as UserAgent
participant "fEMR Dashboard OIDC client (Relying Party)" as RP
participant "Keycloak OIDC Provider (OP)" as OP


note over UserAgent: User visits https:\/\/dashboard.cosri.app
UserAgent->RP: GET https:\/\/dashboard.cosri.app/


# flask-oidc uses deploy-specific config values instead of introspecting .well-known/
RP->OP: GET https:\/\/keycloak.cosri.app/auth/realms/fEMR/.well-known/openid-configuration
OP->RP: JSON metadata document
note left of OP:JSON response:\n{\n "token_endpoint": "https:\/\/keycloak.cosri.app/auth/realms/fEMR/protocol/openid-connect/token", \n "authorization_endpoint ":"https:\/\/keycloak.cosri.app/auth/realms/fEMR/protocol/openid-connect/auth?...",\n ...\n}

RP->UserAgent: 302 Redirect to https:\/\/keycloak.cosri.app/auth/realms/fEMR/protocol/openid-connect/auth?[...]

note left of RP:GET /auth/realms/fEMR/protocol/openid-connect/auth \nparameters:\nstate=xxx (CSRF protection)\nnonce=xxx (server-side replay protection)\nscope=openid email profile\nredirect_uri=https:\/\/dashboard.cosri.app/oidc_callback (OP will redirect here)\nresponse_type=code\nclient_id=xxx (RP identifier)


UserAgent->OP: GET https:\/\/keycloak.cosri.app/auth/realms/fEMR/protocol/openid-connect/auth?[...]
OP->UserAgent: Show hosted login page
UserAgent->OP: Performs login
OP->UserAgent: 302 Redirect to https:\/\/dashboard.cosri.app/oidc_callback?[...] (redirect_uri)

note left of RP:GET /callback parameters:\nstate=xxx\ncode=xxx

UserAgent->RP: GET https:\/\/dashboard.cosri.app/oidc_callback?[...]
RP->OP: POST https:\/\/keycloak.cosri.app/auth/realms/fEMR/protocol/openid-connect/token

note right of RP:POST /auth/realms/fEMR/protocol/openid-connect/token\nparameters:\nclient_id=xxx\nclient_secret=xxx (secret identifying the RP to the OP)\ngrant_type=authorization_code\ncode=xxx\nstate=xxx


OP->RP: JSON {"base64(id_token)", "access_token", ...}

note right of RP:JSON Response:\n{\n "id_token": ADNqVMtqKeYp5w==... # generally a JWT,\n "access_token": xxx # often a JWT,\n "email": "test@dashboard.cosri.app,\n "attribute1": ...,\n "attribute2": ...,\n ...\n}

RP->RP: Verify id_token signature is valid, signed by OP


RP->UserAgent: 302 Redirect https:\/\/dashboard.cosri.app/
note over UserAgent: User is authenticated to https:\/\/dashboard.cosri.app
UserAgent->RP: GET https:\/\/dashboard.cosri.app/
RP->UserAgent: dashboard.cosri.app's page is displayed