Authorization code flow with Proof Key for Code Exchange
The Authorization code flow with Proof Key for Code Exchange, or simply "Auth code flow with PKCE" is the recommended form of authenticating RingCentral users and exchanging tokens in client-side applications. It is considered a more secure version of the more widely used Authorization code flow. The flow is as follows:
}
What are the benefits of using the authorization code flow?
As you can see from the diagram above, the two protocols are nearly identical, with the following differences and benefits:
- two additional tokens are introduced to the flow to combat XSS forgeries
- the client secret is never revealed during the flow
Authorization code flow with PKCE in detail
Step 0. Generate code verifier and code challenge
Before we initiate an authorization request to RingCentral, we need to generate two strings: a code verifier and a code challenge. The code verifier, in particular, should be a cryptographically random string without the '+', '/', and '=' characters.
The code challenge is then derived from the code verifier string generated above. For devices that can perform a SHA256 hash, the code challenge is a Base64, URL-encoded string of the SHA-256 hash of the code verifier. Clients that do not have the ability to perform a SHA-256 hash are permitted to use the plain code verifier string as the challenge.
The code below shows how to generate these two strings:
Javascript developers can install the crypto module like so:
$ npm install crypto
Then your code will look like this:
--8<-- "code-samples/auth/login-url-pkce.js:2:22"
Python developers can install the pkce module like so:
$ pip install pkce
Then in their code it is really simple:
--8<-- "code-samples/auth/pkce.py"
--8<-- "code-samples/auth/pkce.php"
Ruby developers can install the pkce_challenge Gem like so:
$ gem install pkce_challenge
Then in their code:
--8<-- "code-samples/auth/pkce.rb"
Example code verifier and challenge strings
When all is said and done, you will have generated two strings that look similar to the following: A cryptographically-random example string:
# Verifier
pIUgx4tiqFpaOUz0HMc_QbIyQlL901w8mRmkrmhEJ_E
# Challenge
_drLS7o5FwkfUiBhlq2hwJnK_SC6yE7sKOde5O1fdzk
Step 1. Compose a "request authorization" URL
When your application needs to access a user's data, redirect the user to the RingCentral API server. The authorization URL is the same as the URL from Authorization Code Flow Step 1, and PKCE flow will need additional parameters code_challenge and code_challenge_method in the authorization URL:
--8<-- "docs/authentication/login-url-params.inc"
| code_challenge | string | Required. Generated from code challenge.
| code_challenge_method | string | Required. The code challenge method, either plain or S256, depends on whether the challenge is the plain verifier string or the SHA256 hash of the string. If this parameter is omitted, the server assumes plain.
Example Login URL
Below is an example login URL to initiate the PKCE authorization flow. We recommend developers use an SDK to generate this URL in a more automated fashion.
https://platform.ringcentral.com/restapi/oauth/authorize?response_type=code
&redirect_uri=<my_uri>&client_id=<client_id>&display=&prompt=
&code_challenge=<code_challenge_string>&code_challenge_method=S256
Using an SDK to generate a login URL
We recommend developers use an SDK to generate a login URL to ensure it is composed properly.
--8<-- "code-samples/auth/login-url-pkce.js"
Step 2. User login and consent
This step is same as its counterpart in the authorization code flow. After a user logs in and authorizes the application, RingCentral will redirect the user's browser to the redirect_uri provided in the login URL created above. At the same time, RingCentral will append the following query parameters to the redirect URI, which your application will need in subsequent steps.
--8<-- "docs/authentication/auth-code-params.inc"
Example OAuth redirect
HTTP/1.1 302 Found
Location: https://myapp.example.com/oauth2Callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz&expires_in=60
Step 3. Exchange auth code for access token
The 'code' your application receives at your Redirect URI is a temporary authorization code used to obtain an access token to call the API. If the token is not redeemed in the allotted time, the user will need to go through the login and authorization process again. This is the final step before your app can call the RingCentral API.
To exchange an auth code for an access token, developers will call the RingCentral API similarly to how it is done in the authorization code flow, but with the following key differences:
- Clients do not need to transmit client authentication credentials in an
Authorizationheader - Clients need to transmit an additional
code_verifierparameter in the request body
Auth token request
HTTP Headers
| Header | Value |
|---|---|
Content-type |
application/x-www-form-urlencoded |
POST Parameters
--8<-- "docs/authentication/auth-token-params.inc"
| code_verifier | string | Required. Code verifier generated in Step 0. |
Sample Request
POST /restapi/oauth/token HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
code=U0pDMTFQMDFQQVMwM
XxBQUJfTVpHWk5lM29zNVFmWnNHQ01MSmJuMHJmNGlRcnRaeEptTWlPS0MzUTdYRDdSTURiaHBuWHZINGM2WTdqaWlBOE
VhRHNxRWdJVUNYQjd4dmJsWHJoVVlWQVN2SFo2YWJPanJsRkFWZk9SMm5lek0tWnF5d3h8C3AnYOPxO0flEwO6Ffoq9Tl
qs1s&grant_type=authorization_code&client_id=asdsadsadasdadsa&code_verifier=pIUgx4tiqFpaOUz0H
Mc_QbIyQlL901w8mRmkrmhEJ_E&redirect_uri=https%3A%2F%2Fmyapp.acme.com%2Foauth2redirect
Auth token response
The server responds with an access token which can presented in subsequent requests in the HTTP Authorization header to authenticate API Calls. The response will contain the following parameters:
--8<-- "docs/authentication/auth-token-response.inc"
Sample Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token" : "U1BCMDFUMDRKV1MwMXxzLFSvXdw5PHMsVLEn_MrtcyxUsw",
"token_type" : "bearer",
"expires_in" : 7199,
"refresh_token" : "U1BCMDFUMDRKV1MwMXxzLFL4ec6A0XMsUv9wLriecyxS_w",
"refresh_token_expires_in" : 604799,
"scope" : "AccountInfo CallLog ExtensionInfo Messages SMS",
"owner_id" : "256440016"
}