got complete access to a user’s account • Users couldn’t revoke access except by changing their password • Compromised apps exposed the user’s password
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 • Refresh Token: getting a new access token when the first one expires
JavaScript apps: "view source" Native apps: decompile and extract strings Application running on a server Has the ability to keep strings secret since code is running in a trusted environment
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
User: I’d like to use this great app App: Please 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, 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!
accounts.google.com Yes No Allow Example App to access your public profile and contacts? example-app.com/callback Loading… Direct the user to the authorization server ?response_type=code &redirect_uri=example-app.com/callback &state=00000 User signs in Authorization server redirects back to the app ?code=XYZ123&state=00000 Exchange authorization code for an access token
your client 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 code https://example.com/callback?error=access_denied 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
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"}
User: I’d like to use this great app App: Please 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: Here is the temporary code, 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!
your client expects to receive an access token • client_id=CLIENT_ID - The client ID you received when you first created the application • redirect_uri=REDIRECT_URI - Indicates the URI 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
2 Implicit Grant Type?" on developer.okta.com https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type https://oauth.net/2/grant-types/implicit/ • If the server requires a client secret for the Authorization Code flow • If the server doesn't support CORS requests
"code verifier", a random string 43-128 characters long. • Compute the SHA256 hash of the code verifier, call that the code challenge • Include code_challenge=XXXXXX and code_challenge_method=S256 in the initial authorization request • Send the code verifier when exchanging the authorization code for an access token
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 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.
grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID& client_secret=CLIENT_SECRET The user’s credentials are sent directly! Not a good idea for third party apps!
https://api.authorization-server.com/token grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET No user context in the request, so the access token can only be used to access the application’s resources
Request a Device Code { "device_code": "NGU5OWFiNjQ5YmQwNGY3YTdmZTEyNzQ3YzQ1YSA", "user_code": "BDWD-HQPK", "verification_uri": "https://example.com/device", "interval": 5, "expires_in": 1800 } The server responds with a new device code and user code, as well as the URL the user should visit to enter the code.
for the user to enter the code and authorize the application, the device polls the token endpoint. { "access_token": "RsT5OjbzRn430zqMLgV3Ia", "expires_in": 3600, "refresh_token": "b7aab35e97298a060e0ede5b43ed1f70a8" }
OAuth 2.0 • ID Token • /userinfo – for getting more information about the user • Standard set of scopes • openid • profile • email • address • phone • offline_access
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
Defining Scopes 97 • Read / Write • Restrict access to sensitive information • e.g. private repos on GitHub • By functionality • e.g. Google Drive, YouTube, Gmail • Billable resources
• Can easily show a list of active tokens to the user Random String Tokens Cons • Requires storing all active tokens • Resource Server must check the validity with either a DB lookup or HTTP request
(no shared storage between authorization server and resource servers) • Can be validated at the Resource Server without a DB/HTTP lookup Self-Encoded Tokens Cons • Cannot be revoked without storing additional information (defeating the purpose of self-encoded tokens) • Cannot get a list of all active tokens
self-encoded tokens • Limits the risk of leaked tokens • Will annoy developers, so wrap this in an SDK • Short-lived access tokens, no refresh tokens • Limits the ability of apps to work without the user being present • Most likely to frustrate users since they will continually need to log in • Non-expiring access tokens • Easiest for developers • Easiest for users • Highest risk for leaked tokens Access Token Lifetime 108
user? Is your app a SPA or native app? Is the app highly trusted? * Implicit Flow Authorization Code + PKCE Client Credentials Password Authorization Code Yes No SPA Native No Yes No Yes * and no other option is viable Choosing an OAuth Flow