You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+7-7Lines changed: 7 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -179,11 +179,11 @@ Read on for more information about how this package operates behind-the-scenes,
179
179
180
180
The `authorization_code` flow has two phases, which in our case correspond to the `startAuthorizationGrant()` and `completeAuthorizationGrant()` functions in the [AuthCodeController](/src/Controllers/AuthCodeController.php) class:
181
181
182
-
***Phase 1:**`startAuthorizationGrant()` constructs the query parameters that are needed for the call and appends them to `https://api.npr.org/authorization/v2/authorize`. Your router should then redirect the browser to that URL (either using a framework's built-in function such as Laravel's `redirect()->away($url)`, or otherwise just using a good old-fashioned `header("Location: $url")`).
182
+
***Phase 1:**`startAuthorizationGrant()` constructs the query parameters that are needed for the call and appends them to `https://authorization.api.npr.org/v2/authorize`. Your router should then redirect the browser to that URL (either using a framework's built-in function such as Laravel's `redirect()->away($url)`, or otherwise just using a good old-fashioned `header("Location: $url")`).
183
183
184
184
***Phase 2:**`completeAuthorizationGrant()` should be mapped to the `redirect_uri` that you added to your client application in the NPR One [Developer Console](http://dev.npr.org/console). This function has two primary responsibilities:
185
185
1. Validating the `state` parameter that was generated during the `startAuthorizationGrant()` phase. This extra check ensures that your call was not intercepted by a malicious third party.
186
-
1. Exchanging the authorization code for an actual access token using the `POST https://api.npr.org/authorization/v2/token` endpoint.
186
+
1. Exchanging the authorization code for an actual access token using the `POST https://authorization.api.npr.org/v2/token` endpoint.
187
187
188
188
It then saves the token to an unencrypted cookie called `access_token` using our [CookieProvider](/src/Providers/CookieProvider.php) class. **NOTE:** it is *highly* recommended that your client application retrieves the value of the cookie, stores it somewhere locally (HTML5 [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) is a good option), and then **deletes** the cookie. Otherwise, since the cookie is not encrypted it is not considered secure, and may also result in extra overhead on subsequent HTTP requests.
189
189
@@ -193,27 +193,27 @@ Note that the `completeAuthorizationGrant()` function does return an [AccessToke
193
193
194
194
The `device_code` grant similarly has two phases, but requires a little more work on the part of the client. The [DeviceCodeController](/src/Controllers/DeviceCodeController.php) class has two public methods: `startDeviceCodeGrant()` and `pollDeviceCodeGrant()`; each should be mapped to a unique endpoint in your router.
195
195
196
-
***Phase 1:** The client starts off the process by calling the route that corresponds to the `startDeviceCodeGrant()` function, which calls the `POST https://api.npr.org/authorization/v2/device` endpoint and then does two things: one, it safely stores the `device_code` (value) itself, either in an encrypted cookie or using a custom secure storage provider as described [here](#securestorageprovider); and secondly, it returns *everything else* as a JSON object to the consumer. The consumer is then responsible for displaying the `user_code` and `verification_uri` on the screen.
196
+
***Phase 1:** The client starts off the process by calling the route that corresponds to the `startDeviceCodeGrant()` function, which calls the `POST https://authorization.api.npr.org/v2/device` endpoint and then does two things: one, it safely stores the `device_code` (value) itself, either in an encrypted cookie or using a custom secure storage provider as described [here](#securestorageprovider); and secondly, it returns *everything else* as a JSON object to the consumer. The consumer is then responsible for displaying the `user_code` and `verification_uri` on the screen.
197
197
198
-
***Phase 2:** Next, the client is responsible for **polling** the route that corresponds to the `pollDeviceCodeGrant()` function, which calls the `POST https://api.npr.org/authorization/v2/token` endpoint with the securely-stored `device_code` and checks to see whether the user has logged in yet (returning an access token if so, and throwing an Exception if not). This polling should occur at a rate not exceeding the `interval` value in the JSON object returned by the previous call.
198
+
***Phase 2:** Next, the client is responsible for **polling** the route that corresponds to the `pollDeviceCodeGrant()` function, which calls the `POST https://authorization.api.npr.org/v2/token` endpoint with the securely-stored `device_code` and checks to see whether the user has logged in yet (returning an access token if so, and throwing an Exception if not). This polling should occur at a rate not exceeding the `interval` value in the JSON object returned by the previous call.
199
199
200
200
All device code/user code pairs will expire within the `expires_in` value in the JSON object returned by the previous call (this value represents a TTL in seconds). The client application is responsible for calling the route that corresponds to the `startDeviceCodeGrant()` function to restart this process if the user fails to log in before the device code expires.
201
201
202
202
### Refresh Token Grant
203
203
204
204
The `refresh_token` that is generated in association with every new access token should be stored securely either in an encrypted cookie or by using a custom secure storage provider as described [here](#securestorageprovider). The [RefreshTokenController](/src/Controllers/RefreshTokenController.php) class is thus refreshingly simple and has one method:
205
205
206
-
*`generateNewAccessTokenFromRefreshToken()` looks for this `refresh_token` in the secure storage provider and (if found) uses the `refresh_token` grant provided by the `POST https://api.npr.org/authorization/v2/token` endpoint to obtain a new access token for the user. (And in case you were wondering: yes, that call will result in a new `refresh_token` being generated, which is then saved to the secure storage layer in the exact same way.)
206
+
*`generateNewAccessTokenFromRefreshToken()` looks for this `refresh_token` in the secure storage provider and (if found) uses the `refresh_token` grant provided by the `POST https://authorization.api.npr.org/v2/token` endpoint to obtain a new access token for the user. (And in case you were wondering: yes, that call will result in a new `refresh_token` being generated, which is then saved to the secure storage layer in the exact same way.)
207
207
208
208
This method should be called when any client application that has previously obtained a valid access token suddenly receives a `401 Unauthorized` response from any of our micro-services, indicating that the access token has expired. This error should call the endpoint in your router that calls `generateNewAccessTokenFromRefreshToken()`. A new access token will be generated and returned as raw JSON (where it is up to the client application to store it securely). If a new access token could not be generated, the client may retry the call up to 2-3 times, but after that point the user should be considered logged out and prompted to log in again.
209
209
210
210
**Optional implementation:** The [AccessTokenModel](/src/Models/AccessTokenModel.php) and the corresponding JSON output do include an `expires_in` value (TTL in seconds) for the access token, so the client application *may* choose (but is not required) to call the route corresponding to `generateNewAccessTokenFromRefreshToken()` before the token actually expires, _or_ after it was set to expire but before another API call is attempted. Note that regardless of whether it had already expired or not, the original access token **will** be deleted immediately as part of that call.
211
211
212
212
### Logout/Disconnect
213
213
214
-
We ask all clients to help secure user data and free up unused resources in our system by implementing a form of logout functionality that will revoke the user’s previously-generated access tokens and refresh tokens through the `POST https://api.npr.org/authorization/v2/token/revoke` endpoint. The `deleteAccessAndRefreshTokens()` function in the [LogoutController](/src/Controllers/LogoutController.php) class will perform this task, in addition to deleting the `refresh_token` that was previously saved to an encrypted cookie or your custom [secure storage provider](#securestorageprovider). Your client application can be ignorant of whatever mechanism you're using to securely store the refresh token and safely assume that it is properly removed as part of logout.
214
+
We ask all clients to help secure user data and free up unused resources in our system by implementing a form of logout functionality that will revoke the user’s previously-generated access tokens and refresh tokens through the `POST https://authorization.api.npr.org/v2/token/revoke` endpoint. The `deleteAccessAndRefreshTokens()` function in the [LogoutController](/src/Controllers/LogoutController.php) class will perform this task, in addition to deleting the `refresh_token` that was previously saved to an encrypted cookie or your custom [secure storage provider](#securestorageprovider). Your client application can be ignorant of whatever mechanism you're using to securely store the refresh token and safely assume that it is properly removed as part of logout.
215
215
216
-
As described in the [NPR One API Reference](http://dev.npr.org/api), the `POST https://api.npr.org/authorization/v2/token/revoke` endpoint takes in either an access token or a refresh token. By default, it's assumed to be an access token, but it will delete **both** regardless of which of the two is passed in. Therefore, the `deleteAccessAndRefreshTokens()` function _can_ take in an access token, but if none is provided, it will look for a refresh token and, if found, use that to revoke the pair of tokens. It is recommended to pass in the access token if you have it (especially for client applications developed prior to summer 2016, when refresh tokens were first introduced). If you are certain that refresh tokens have been issued for all your users and there is no chance that they have been removed by other client-side code, you can safely call `deleteAccessAndRefreshTokens()` without any parameters.
216
+
As described in the [NPR One API Reference](http://dev.npr.org/api), the `POST https://authorization.api.npr.org/v2/token/revoke` endpoint takes in either an access token or a refresh token. By default, it's assumed to be an access token, but it will delete **both** regardless of which of the two is passed in. Therefore, the `deleteAccessAndRefreshTokens()` function _can_ take in an access token, but if none is provided, it will look for a refresh token and, if found, use that to revoke the pair of tokens. It is recommended to pass in the access token if you have it (especially for client applications developed prior to summer 2016, when refresh tokens were first introduced). If you are certain that refresh tokens have been issued for all your users and there is no chance that they have been removed by other client-side code, you can safely call `deleteAccessAndRefreshTokens()` without any parameters.
217
217
218
218
This proxy does not impose any requirements for how you set up and call your endpoints (save for what is strictly required by the OAuth 2.0 spec), so the access token parameter needed for the `deleteAccessAndRefreshTokens()` function can be obtained from a variety of sources: via a query parameter, form `POST` data, a `POST` with a JSON body, and potentially even a cookie, if that is how you are storing your access tokens client-side. The example [Router.php](/examples/Router.php) file uses a query parameter for simplicity's sake. In most cases, `POST` requests with form data or JSON bodies are preferable because they are slightly harder to intercept over insecure networks, but since the assumption here is that the access token will be revoked almost immediately, keeping the token secure is not a huge concern.
0 commit comments