By the end of the lesson, you can say what OAuth 2.0 is for and what OpenID Connect is for, you can list the actors of OAuth, you can describe the steps of the authorization code flow, and you can tell an access token from an ID token.
Why don't we hand over the password?
Kurzuspont would like to save the student's timetable into an external calendar. It would be a bad solution to ask for the student's password at the calendar provider: Kurzuspont could then do anything on the student's behalf, and could even leak the password. The solution is delegated access: the student logs in at the calendar provider, decides there what to allow Kurzuspont, and Kurzuspont receives a token with limited authorization. The password stays with the calendar provider. The OAuth 2.0 framework is for this.
flowchart LR
U[Student] --> A[Kurzuspont]
A -->|asks for access| I[Authorization provider]
U -->|decides there| I
I -->|access token| A
A -->|token in the request| N[Calendar API]
The actors of OAuth 2.0
RFC 6749 distinguishes four roles:
Role
Name in the RFC
Example
The party granting access
resource owner
the student
The application requesting access
client
Kurzuspont
The server issuing the token
authorization server
the authorization server of the calendar provider
The server holding the protected resource
resource server
the calendar's API
Separating the roles helps in understanding that a token is not a general "I am logged in everywhere" proof: it is for reaching a defined resource, according to the given permission and validity conditions.
The authorization code flow
According to RFC 6749 the steps of the authorization code flow are:
The client directs the user to the authorization server, giving its identifier, the requested scope, and a redirect address.
The authorization server identifies the user, who grants or denies access.
If they grant it, the server redirects the user back to the client's address with an authorization code.
The client sends the code to the token endpoint of the authorization server, authenticating itself meanwhile.
The server checks the code and issues the access token (and optionally a refresh token).
sequenceDiagram
actor H as Student
participant K as Kurzuspont (client)
participant E as Authorization server
participant N as Calendar API
H->>K: Save the timetable to the calendar
K-->>H: Redirect to the authorization server
H->>E: Logs in, grants permission
E-->>H: Redirect to Kurzuspont + authorization code
H->>K: Authorization code
K->>E: Redeem the code (request the token)
E-->>K: Access token
K->>N: Request + token
N-->>K: Result of the calendar operation
The diagram is conceptual, not a complete sequence of protocol messages. The code passes through the browser, while the token travels directly between the client and the authorization server, so only the short-lived code reaches the browser.
PKCE: protection against interception of the code
The authorization code can pass through a channel (the redirect address) that another program can intercept. PKCE (Proof Key for Code Exchange, RFC 7636) protects against this with a per-request secret: the client makes a random code_verifier, sends a code_challenge formed from its SHA-256 digest in the first request, and the original verifier when redeeming the code. The server recomputes the digest and compares; if it differs, it rejects. An intercepted code cannot thus be redeemed without the verifier.
We tried it with the example values of RFC 7636 (Node.js crypto):
The result equals the code_challenge value in the RFC. According to RFC 9700 (the OAuth 2.0 security recommendation) PKCE is mandatory for public clients (for example mobile and browser applications), recommended for confidential clients as well, and the S256 method must be used. The same RFC also says that clients should not use the implicit flow, in which the access token arrives directly in the authorization response, because it can leak through the URL, the history, or the Referer header.
OAuth 2.0 by itself is not a login
OAuth 2.0 tells how a client can obtain limited access to a resource. It does not tell who the user is for the client. An access token must therefore not be interpreted automatically as proof of identity. The form of the token is not necessarily a JWT either: it can be a value opaque to the client.
OpenID Connect: identity for the client
According to the specification of the OpenID Foundation, OpenID Connect (OIDC) is a simple identity layer on top of OAuth 2.0: it allows the client to verify who the user is, based on the authentication performed by the authorization server. Its most important device is the ID token (ID stands for "identity"), which is a JWT (7.3) and contains claims about the authentication of the user:
Claim
Meaning
iss (issuer)
Who issued the token (an https address).
sub (subject)
The identifier of the user at the issuer, locally unique and never reused.
aud (audience)
Whom it is for: it must contain the client's identifier.
exp (expiration)
Until when it can be accepted.
The client must check the ID token for its own purpose (issuer, audience, expiry, signature). It does not replace the access token meant for an API.
flowchart TD
T[What does the application want?] -->|use an external API| O[OAuth 2.0: delegated access]
T -->|log the user in| I[OpenID Connect: identity]
The application's own session can also get a lifecycle separate from the login at the external provider. After a successful external authentication the local application must still decide what resources of its own it gives the recognized user access to. External identification does not give automatic authorization (7.4).
Worked example: two tasks in Kurzuspont
Task
Protocol
What does Kurzuspont receive?
The student logs in with their university identifier
OpenID Connect
An ID token: who the student is (sub), who issued it (iss).
Saving the timetable into the student's external calendar
OAuth 2.0
An access token for the calendar API, with a limited scope.
In one user experience the two flows can be joined ("Log in and authorize the calendar"), but conceptually they differ: the first identifies, the second delegates access. In both, Kurzuspont's own authorization decision (7.4) remains in force.
Common misconceptions
Statement
Clarification
"OAuth 2.0 by itself is a login protocol."
Its primary goal is delegated access; for identity, OIDC provides the protocol.
"The access token tells the client who the user is."
It represents the access meant for the resource server, it is not an identity claim.
"Any API can be called with an ID token."
The ID token is an authentication claim addressed to the client.
"After an external login every local operation is allowed."
The local service's own authorization decision is needed.
"PKCE is needed only for mobile apps."
According to RFC 9700 it is mandatory for public clients, recommended for the others.
In brief
OAuth 2.0 is delegated access: the client gets a limited token without the password.
OAuth 2.0 and OpenID Connect
Objectives
By the end of the lesson, you can say what OAuth 2.0 is for and what OpenID Connect is for, you can list the actors of OAuth, you can describe the steps of the authorization code flow, and you can tell an access token from an ID token.
Why don't we hand over the password?
Kurzuspont would like to save the student's timetable into an external calendar. It would be a bad solution to ask for the student's password at the calendar provider: Kurzuspont could then do anything on the student's behalf, and could even leak the password. The solution is delegated access: the student logs in at the calendar provider, decides there what to allow Kurzuspont, and Kurzuspont receives a token with limited authorization. The password stays with the calendar provider. The OAuth 2.0 framework is for this.
flowchart LR U[Student] --> A[Kurzuspont] A -->|asks for access| I[Authorization provider] U -->|decides there| I I -->|access token| A A -->|token in the request| N[Calendar API]The actors of OAuth 2.0
RFC 6749 distinguishes four roles:
Separating the roles helps in understanding that a token is not a general "I am logged in everywhere" proof: it is for reaching a defined resource, according to the given permission and validity conditions.
The authorization code flow
According to RFC 6749 the steps of the authorization code flow are:
sequenceDiagram actor H as Student participant K as Kurzuspont (client) participant E as Authorization server participant N as Calendar API H->>K: Save the timetable to the calendar K-->>H: Redirect to the authorization server H->>E: Logs in, grants permission E-->>H: Redirect to Kurzuspont + authorization code H->>K: Authorization code K->>E: Redeem the code (request the token) E-->>K: Access token K->>N: Request + token N-->>K: Result of the calendar operationThe diagram is conceptual, not a complete sequence of protocol messages. The code passes through the browser, while the token travels directly between the client and the authorization server, so only the short-lived code reaches the browser.
PKCE: protection against interception of the code
The authorization code can pass through a channel (the redirect address) that another program can intercept. PKCE (Proof Key for Code Exchange, RFC 7636) protects against this with a per-request secret: the client makes a random
code_verifier, sends acode_challengeformed from its SHA-256 digest in the first request, and the originalverifierwhen redeeming the code. The server recomputes the digest and compares; if it differs, it rejects. An intercepted code cannot thus be redeemed without the verifier.We tried it with the example values of RFC 7636 (Node.js
crypto):The result equals the
code_challengevalue in the RFC. According to RFC 9700 (the OAuth 2.0 security recommendation) PKCE is mandatory for public clients (for example mobile and browser applications), recommended for confidential clients as well, and theS256method must be used. The same RFC also says that clients should not use the implicit flow, in which the access token arrives directly in the authorization response, because it can leak through the URL, the history, or the Referer header.OAuth 2.0 by itself is not a login
OAuth 2.0 tells how a client can obtain limited access to a resource. It does not tell who the user is for the client. An access token must therefore not be interpreted automatically as proof of identity. The form of the token is not necessarily a JWT either: it can be a value opaque to the client.
OpenID Connect: identity for the client
According to the specification of the OpenID Foundation, OpenID Connect (OIDC) is a simple identity layer on top of OAuth 2.0: it allows the client to verify who the user is, based on the authentication performed by the authorization server. Its most important device is the ID token (ID stands for "identity"), which is a JWT (7.3) and contains claims about the authentication of the user:
iss(issuer)httpsaddress).sub(subject)aud(audience)exp(expiration)The client must check the ID token for its own purpose (issuer, audience, expiry, signature). It does not replace the access token meant for an API.
flowchart TD T[What does the application want?] -->|use an external API| O[OAuth 2.0: delegated access] T -->|log the user in| I[OpenID Connect: identity]The application's own session can also get a lifecycle separate from the login at the external provider. After a successful external authentication the local application must still decide what resources of its own it gives the recognized user access to. External identification does not give automatic authorization (7.4).
Worked example: two tasks in Kurzuspont
sub), who issued it (iss).In one user experience the two flows can be joined ("Log in and authorize the calendar"), but conceptually they differ: the first identifies, the second delegates access. In both, Kurzuspont's own authorization decision (7.4) remains in force.
Common misconceptions
In brief
iss,sub,aud,exp).Review questions
Learning resources