Chome Plugins with OAuth2 + OpenConnect ID | Anton’s Blog on WordPress.com
In writing this I’m going to assume you have some background around how OAuth2 + OpenConnectID work. I will not be talking about token types, the difference between authentication and authorization, or grants and scopes. I have future plans to write some more basic guides, but the intention of this article is to explain how you can provide secure authentication for your Chrome Plugin.
The flow we are going to use is called a Hybrid flow, and it will be protected by PKCE (pronounced pixie). Before we get into the details of the Hybrid flow, let’s have a quick look at the players in this interaction, and why some of the other flows are inappropriate.
Scenario:
You are building a Chrome plugin that needs to access user specific data from an API call. Doing so requires the user to be authenticated and the user does not want to have to login every hour, nor have to re-login after closing their browser (restarting their PC).
Players:
User — Person sitting at the computer, using your Google Chrome Plugin
Client — Your Google Chrome Plugin
Identity Provider (IdP) — Your OAuth2 + OpenConnectID server (In our case running IdentityServer4)
Resource Provider — The API where the data needs to come from, belonging to the User, for display in the Client
Auth Code Flow and why it is inappropriate…
The main purpose of the auth code flow is to protect the access token used to call the API by never sending it back to the browser.
- Client detects User has not yet authenticated and so and gets redirected to the IdP login screen
- User puts in their username and password
- IdP validates the User credentials then issues a 302 redirect back to Client providing it with a JWT identity token and an authorization code
- Client makes a back-end call to the IdP providing its client secret and the authorization code
- Authorization code and is exchanged it for an access token
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(2)
+----|-----+ Client Identifier +---------------+
| -+----(1)-- & Redirection URI ---->| |
| User- | | Authorization |
| Agent -+----(2)-- User authenticates --->| Server |
| | | |
| -+----(3)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(1) (3) | |
| | | |
^ v | |
+---------+ | |
| |>---(4)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | |
| |<---(5)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)To work, the client needs to know the client secret. Since we are building a Chrome plugin it’s likely going to be written in JavaScript. This means the client secret is available for exploitation by anybody who can read/decompile code.
Implicit Flow and why it is inappropriate…
Implicit flow accounts for the client secret vulnerability inherent in Auth Code Flow by not requiring one.
- Client calls the IdP providing the client secret and gets redirected to a login screen
- User puts in their username and password
- IdP issues a 302 redirect providing browser with an access token
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(2)
+----|-----+ Client Identifier +---------------+
| -+----(1)-- & Redirection URI --->| |
| User- | | Authorization |
| Agent -|----(2)-- User authenticates -->| Server |
| | | |
| |<---(3)--- Redirection URI ----<| |
| | with Access Token +---------------+
| |
+-|--------+
| |
(1) (3) Access Token
| |
^ v
+---------+
| |
| Client |
| |
+---------+Because the client, in this case, is inside the browser the access token it holds is open to vulnerabilities such as cross-site scripting. Any malicious application can take the access token and use it to gain access to your API. While implicit flow blocks the usage of refresh tokens there is still a window of opportunity where the token can be compromised.
Enter Hybrid + PKCE Flow…
- Client initiates a request for protected data by generating a verifier (a high-entropy cryptographic random string), hash it with SHA256 and hits the IdP
- IdP detects user is not authenticated and shows the User the login screen to put in their username and password
- IdP issues a 302 redirect providing the Client with a JWT identity token and an authorization code then redirects back to a known endpoint for the Client to detect and can close the login dialog
- Client calls the IdP a second time on a back-end channel providing its the authorisation code and the original unhashed verifier
- Authorisation code and verifier are exchanged for an access token
+----------+
| Resource |
| Owner |
| |
+----------+
^
|
(2)
+----|-----+ Client Identifier +---------------+
| -+----(1)-- & Redirection URI ---->| |
| | & SHA256 verifier ---->| |
| User- | | Authorization |
| Agent -+----(2)-- User authenticates --->| Server |
| | | |
| -+----(3)-- Authorization Code ---<| |
+-|----|---+ +---------------+
| | ^ v
(1) (3) | |
| | | |
^ v | |
+---------+ | |
| |>---(4)-- Authorization Code ---------' |
| Client | & Redirection URI |
| | & Original verifier |
| | |
| |<---(5)----- Access Token -------------------'
+---------+ (w/ Optional Refresh Token)And there you have it. Hybrid + PKCE is still reasonably new so it may be subject to change, but I don’t anticipate it being superseded anytime soon.
If you are after some more in-depth technical explanation check out RFC 7636…
Originally published at isitaboutmycube.wordpress.com on August 9, 2017.
Unmodified ASCII art available from ReadTheDocs.
