to obtain an access token ▸ Authorization Code Flow: web apps, native apps ▸ Device Flow: browserless or input-constrained devices ▸ Password: not really OAuth, only for first-party apps ▸ Client Credentials: for machine-to-machine authentication
to access a user's data? Can the app use a browser on the device? Is this a first-party app? Implicit Flow Authorization Code + PKCE Client Credentials Password Authorization Code No Yes No Yes Yes No Yes No Device Flow Do you need to avoid redirects? No Yes Can the app make a cross-domain POST? No Yes or N/A Is this a first- party app, and is there a keyboard? No Yes Choosing an OAuth Flow
a keyboard? Is the app trying to access a user's data? Can the app use a browser on the device? Is this a first-party app? Implicit Flow Authorization Code + PKCE Client Credentials Password Authorization Code No Yes No Yes Yes No Yes No Device Flow Do you need to avoid redirects? No Yes Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Choosing an OAuth Flow
the ability to keep strings secret since code is running in a trusted environment The application can't keep strings secret JavaScript/Single-Page apps: "view source" Native apps: decompile and extract strings
a keyboard? Can the app use a browser on the device? Is this a first-party app? Implicit Flow Authorization Code + PKCE Client Credentials Password Authorization Code No No Yes Yes No Yes No Device Flow Do you need to avoid redirects? No Yes Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Choosing an OAuth Flow
a keyboard? Can the app use a browser on the device? Is this a first-party app? Implicit Flow Authorization Code + PKCE Password Authorization Code No Yes Yes No Yes No Device Flow Do you need to avoid redirects? No Yes Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Client Credentials No Choosing an OAuth Flow
a keyboard? Can the app use a browser on the device? Implicit Flow Authorization Code + PKCE Client Credentials Password Authorization Code No No Yes No Yes No Device Flow Do you need to avoid redirects? No Yes Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Is this a first-party app? Yes Choosing an OAuth Flow
a keyboard? Can the app use a browser on the device? Implicit Flow Authorization Code + PKCE Client Credentials Password Authorization Code No No Yes No No Device Flow No Yes Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Is this a first-party app? Yes Choosing an OAuth Flow Yes Do you need to avoid redirects?
a keyboard? Can the app use a browser on the device? Implicit Flow Authorization Code + PKCE Client Credentials Authorization Code No No Yes No No Device Flow No Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Is this a first-party app? Yes Choosing an OAuth Flow Yes Do you need to avoid redirects? Password Yes
grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID& client_secret=CLIENT_SECRET The user’s credentials are sent directly! Don't let third party apps do this!
all of these criteria: • Is a first-party app • (the user is logging in to an app branded the same as their account) • Cannot launch/redirect a browser to the authorization server • You do not need to support multifactor auth or delegated accounts
is there a keyboard? Can the app use a browser on the device? Implicit Flow Authorization Code + PKCE Client Credentials No No Yes No No Device Flow Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Is this a first-party app? Yes Choosing an OAuth Flow Yes Do you need to avoid redirects? Authorization Code No
and is there a keyboard? Can the app use a browser on the device? Implicit Flow Authorization Code + PKCE Client Credentials No No Yes No Device Flow Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Is the app trying to access a user's data? Yes Is this a first-party app? Yes Choosing an OAuth Flow Yes Do you need to avoid redirects? Authorization Code No
go to the authorization server to grant me access User: I’d like to log in to “The Best App Ever”, it wants to access my photos AS: Here is a temporary code the app can use App: Here is the temporary code, and my secret, please give me a token User: Here is the temporary code, please use this to get a token AS: Here is an access token! App: Please let me access this user’s data with this access token! User Agent App OAuth Server API
address bar The user, or malicious software, can modify the requests and responses Sent from server to server Code is run on a server, not on the user's computer, so requests cannot be tampered with
the right server ‣ Connection from app to server can't be tampered with ‣ Response from the server can be trusted because it came back in the same connection
the receiver will get the data ▸ Data leak in browser history ▸ The data is written to the browser history which may be synced to "the cloud" or other devices Any data received via the front channel must be verified before it is used! FRONT-CHANNEL RISKS
- indicates that your app expects to receive an authorization code • client_id=CLIENT_ID - The client ID you received when you first created the application • redirect_uri=REDIRECT_URI - Indicates the URL to return the user to after authorization is complete, such as https://example-app.com/callback • scope=photos - A space-separated string indicating which parts of the user's account you wish to access • state=1234zyx - A random string generated by your application, which you'll verify later
authorization https://example.com/callback?error=access_denied&state=1234xyz The user is redirected back to the application with an error code If User Denies If User Allows https://example.com/callback? code=AUTH_CODE_HERE& state=1234zyx
value it started with • This lets the application be sure it isn't trying to exchange an attacker's authorization code The app must do this because it received the authorization code via the front channel!
grant_type=authorization_code - indicates that this request contains an authorization code • code=CODE_FROM_QUERY - Include the authorization code from the query string of this request • redirect_uri=REDIRECT_URI - This must match the redirect_uri used in the original request • client_id=CLIENT_ID - The client ID you received when you first created the application • client_secret=CLIENT_SECRET - Since this request is made from server-side code, the secret is included
"refresh_token":"64d049f8b21191e12522d5d96d5641af5e8" } The server replies with an access token and expiration time or if there was an error: {"error":"invalid_request"}
a keyboard? Can the app use a browser on the device? Implicit Flow Authorization Code + PKCE No Yes No Device Flow Can the app make a cross-domain POST? No Yes or N/A No Yes Password Yes Client Credentials Is this a confidential client? Is the app trying to access a user's data? Yes Is this a first-party app? Yes Choosing an OAuth Flow Yes Do you need to avoid redirects? Authorization Code No No No
to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a first- party app, and is there a keyboard? Implicit Flow Authorization Code + PKCE Yes No Device Flow Can the app make a cross-domain POST? No Yes or N/A No Yes Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device?
to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a first- party app, and is there a keyboard? Implicit Flow Authorization Code + PKCE No Device Flow No Yes or N/A No Yes Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Yes Can the app make a cross-domain POST?
to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a first- party app, and is there a keyboard? Implicit Flow No Device Flow No No Yes Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Yes Can the app make a cross-domain POST? Authorization Code + PKCE Yes or N/A
the front channel • so it can't guarantee it was actually received by the correct application • it needs a way to verify that the correct application is using it to get a token • Normally the client_secret solves this, but we can't use a secret!
go to the authorization server to grant me access, take this hash with you User: I’d like to log in to this app, here's the hashed secret it gave me AS: Here is a temporary code the app can use App: Here's the code, and the plaintext secret, please give me a token User: Here is the temporary code, please use this to get a token AS: Let me verify the hash of that secret... ok here is an access token! App: Please let me access this user’s data with this access token! App: Hang on while I generate a new secret and hash it User Agent App OAuth Server API
characters long ipSBt30y48l401NGbLjo026cqwsRQzR5KI40AuLAdZ8 The challenge is the SHA256 hash of the verifier string base64url(sha256(code_verifier)) Generate the Code Challenge
authorization code example://callback?error=access_denied&state=1234xyz The user is redirected back to the application with an error code If User Denies If User Allows example://callback? code=AUTH_CODE_HERE& state=1234zyx
make a POST request: • grant_type=authorization_code - indicates that this request contains an authorization code • code=CODE_FROM_QUERY - Include the authorization code from the query string of this request • redirect_uri=REDIRECT_URI - This must match the redirect_uri used in the original request • client_id=CLIENT_ID - The client ID you received when you first created the application • code_verifier=VERIFIER_STRING - The plaintext code verifier initially created
"refresh_token":"64d049f8b2119a12522d5dd96d5641af5e8" } The server compares the code_verifier with the code_challenge that was in the request when it generated the authorization code, and responds with an access token.
public client • Is able to launch/redirect a browser to the authorization server • Can make a POST request to the token endpoint • e.g. for JavaScript apps, the auth server supports CORS requests
Password Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a first- party app, and is there a keyboard? No Device Flow No Yes Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Yes Can the app make a cross-domain POST? Implicit Flow No
go to the authorization server to grant me access User: I’d like to log in to “The Best App Ever”, it wants to access my photos AS: Here is an access token! App: Please let me access this user’s data with this access token! User Agent App OAuth Server API
- indicates that your app expects to receive an authorization code • client_id=CLIENT_ID - The client ID you received when you first created the application • redirect_uri=REDIRECT_URI - Indicates the URL to return the user to after authorization is complete, such as https://example-app.com/callback • scope=photos - A space-separated string indicating which parts of the user's account you wish to access • state=1234zyx - A random string generated by your application, which you'll verify later
an error code If User Denies The auth server redirects with the access token in the URL If User Allows https://example.com/auth#token=ACCESS_TOKEN&state=1234xyz
It's possible to intercept the access token during the redirect, and no way to detect this • Access token leak in browser history • The access token is stored in the browser history, which may be synced to multiple devices • Access token leak to scripts • The access token will be visible to all third-party scripts on the page, e.g. analytics, ads, etc
all of these criteria: • Is a JavaScript app running in a browser • Has no server-side component • The OAuth server you are using does not allow cross-domain requests • If you have no other option, because really...
Password Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a first- party app, and is there a keyboard? No Device Flow No Yes Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Yes Can the app make a cross-domain POST? Implicit Flow No
a keyboard? No Yes Yes Can the app make a cross-domain POST? Implicit Flow No Authorization Code + PKCE Yes or N/A Yes Yes Password Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Device Flow No Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device?
Implicit Flow No Authorization Code + PKCE Yes or N/A Yes Yes Password Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Device Flow No Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Is this a first- party app, and is there a keyboard? No
Flow No Authorization Code + PKCE Yes or N/A Yes Yes Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Device Flow No Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Is this a first- party app, and is there a keyboard? No Yes Password
POST? Implicit Flow No Authorization Code + PKCE Yes or N/A Yes Yes Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Is this a first- party app, and is there a keyboard? No Device Flow No
"https://example.com/device", "expires_in": 1800, "interval": 5 } The server responds with a new device code and user code, as well as the URL the user should visit to enter the code.
code and authorize the application, the device polls the token endpoint. { "error": "authorization_pending" } POST https://authorization-server.com/token grant_type=urn:ietf:params:oauth:grant- type:device_code &client_id=CLIENT_ID &device_code=NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA
code and authorize the application, the device polls the token endpoint. { "error": "authorization_pending" } POST https://authorization-server.com/token grant_type=urn:ietf:params:oauth:grant- type:device_code &client_id=CLIENT_ID &device_code=NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA
code and authorize the application, the device polls the token endpoint. { "error": "authorization_pending" } POST https://authorization-server.com/token grant_type=urn:ietf:params:oauth:grant- type:device_code &client_id=CLIENT_ID &device_code=NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA
code and authorize the application, the device polls the token endpoint. { "error": "authorization_pending" } POST https://authorization-server.com/token grant_type=urn:ietf:params:oauth:grant- type:device_code &client_id=CLIENT_ID &device_code=NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA
code and authorize the application, the device polls the token endpoint. { "access_token": "RsT5OjbzRn430zqMLgV3Ia", "expires_in": 3600, "refresh_token": "b7aab35e97298a060e0ede5b43ed1f70a8" } POST https://authorization-server.com/token grant_type=urn:ietf:params:oauth:grant- type:device_code &client_id=CLIENT_ID &device_code=NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA
POST? Implicit Flow No Authorization Code + PKCE Yes or N/A Yes Yes Client Credentials Is the app trying to access a user's data? Yes Is this a first-party app? Yes Do you need to avoid redirects? Authorization Code No No No Is this a confidential client? Choosing an OAuth Flow No Can the app use a browser on the device? Is this a first- party app, and is there a keyboard? No Device Flow No
HAiOjE1MjQ1OTg1MTAsImp0aSI6IklELklfNUc4RzhWdXowMHJvYl9aSzlja3J0T0pseVdwNzh xMU5naGV2QlJ6dkEiLCJhbXIiOlsicHdkIl0sImlkcCI6IjAwb2NxM2J3aTFoTnpRT3B5MGg3I iwibm9uY2UiOiJhYmMiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJwYWRtYS5nb3ZpbmRhcmFqYWx 1QG9rdGEuY29tIiwiZ2l2ZW5fbmFtZSI6IlBhZG1hIiwibWlkZGxlX25hbWUiOiJLcmlzaG5hI iwiZmFtaWx5X25hbWUiOiJHb3ZpbmRhcmFqYWx1Iiwiem9uZWluZm8iOiJBbWVyaWNhL0xvc19 BbmdlbGVzIiwidXBkYXRlZF9hdCI6MTUyNDU5NDM2MSwiYXV0aF90aW1lIjoxNTI0NTk0OTA3f Q.HvMYW8XbdCf1BWZfHQ1odaAYJjZqKkh1NUkHW0clk6J7pYunn8jllbIp0IhSjcCn6PBIlZPr rE0dkuyjvdHjVI8ALQNwtM7FnIs9H6gCH0oONx4EL4KEf4d_w46qeqsCwMClvNoaE3c2I5kONu JUlaefbnr6Al_y9z5mvLyDynf9IjrOyTPoIrgk9V46l28Aulp4dJhqBtZfpYyVbKrXawHSO5Fv KTDMPBhQgxt0_6PKG7sSkhbMeBicIc35SJJaXt81KSfkYDUp5s1UQ74ATHrtLe7HMU1yp_Kajg YUKxMXO5NiXpeNEHzarAOWzLHblrQcgkpuJbY3KM1HHg&state=xyz1234 The user is redirected back to the redirect_uri with an ID token
right auth server? • audience (aud) – is the token intended for my application? • expiry time (exp) – has the current time already passed the exp time? • issued at time (iat) – is the current time too far from the issued time? • nonce - does it match the nonce passed in the request? Validating the Claims