How to setup PKCE for oAuth2.0 - Authorization Grant type ?SummaryPKCE (RFC 7636) is a technique to secure public clients that don't use a client secret. It is primarily used by native and mobile apps, but the technique can be applied to any public client as well. This article explains the steps required to complete PKCE for oAuth 2.0 within ServiceNow. How does this feature work? The client creates and records a secret named the "code_verifier" and derives a transformed version "t(code_verifier)" (referred to as the "code_challenge"), which is sent in the OAuthAuthorization Request along with the transformation method "t_m".The Authorization Endpoint responds as usual but records "t(code_verifier)" and the transformation method.The client then sends the authorization code in the Access Token Request as usual but includes the "code_verifier" secret generated at (A).The authorization server transforms "code_verifier" and compares it to "t(code_verifier)" from (B). Access is denied if they are not equal. Provider configurations oAuth provider could be ServiceNow or Third party.ServiceNow is the oAuth provider if you want to use token for inbound API call.Third party is the oAuth provider if you want to use oauth for outbound rest message. System oAuth > Application Registry > Create an OAuth API endpoint for external clients oAuth Parameters Description Client ID Auto-generated Client Secret Auto-generated Redirect URL callback URL for the token consumer.Check with a third party for the callback URL Refresh Token Lifespan The lifespan of the refresh token in seconds Access Token Lifespan The lifespan of the refresh token in seconds PKCE required Check field Consumer configurations These are the possible configurations to connect with third-party OAuth provider to consume token. Contact vendor ( oAuth Provider ) if you are aware of the required values for oauth configurations.This table has the values specific to ServiceNow if ServiceNow is the oAuth provider. System oAuth > Application Registry > Connect to a third party OAuth Provider oAuth Parameters Description Client ID Client ID is generated once the application is registered. Client Secret Client Secret is generated once the application is registered. PKCE Required Check if the Authorization grant flow requires PKCE. Code challenge method Type of code challenge method. Authorization URL ServiceNow uses oauth_auth.do. Token URL ServiceNow uses oauth_token.do. Token revocation URL ServiceNow uses oauth_revoke.do. Redirect URL ServiceNow uses oauth_redirect.do. oAuth Provider configurations oAuth entity profile is created by default in the NOW platform. This profile is referenced in the outbound rest message to consume tokens from third-party OAuth providers. oAuth Entity Scopes - Scopes are required to define the permissions for the access token. It is recommended to check with the vendor to know the scopes required to access any API. Use PKCE flow to get access token If you are making an outbound rest message call from ServiceNow select the authentication type as "oAuth 2.0" and select oAuth Profile created in the consumer configurations.Once the OAuth profile is selectedClick Get oAuth Token-related link to generate a token.You will be redirected to login page to sign in.After successful login user is redirected to the consent page to Allow/Deny the request.Click "Allow" to generate a token.Token details will be shown in the info message.Test outbound rest message with the generated token. Scripted Rest Message This script works if the access & refresh token is generated successfully using Get oAuth Token ui action. restapi_call_using_token();function restapi_call_using_token(){var r = new sn_ws.RESTMessageV2('Amazon Web Services', 'get');var response = r.execute();var responseBody = response.getBody();var httpStatus = response.getStatusCode();gs.print("API response received");gs.print("response"+response);gs.print("responseBody"+responseBody);}*** Script: API response received*** Script: response[object RESTResponseV2]*** Script: responseBody{"result":[{"parent":"","made_sla":"false","caused_by":"","watch_list":"","upon_reject":"","sys_updated_on":"2017-08-29 20:16:07","child_incidents":"","hold_reason":"","approval_history":"","skills":"","number":"INC0000001","resolved_by":{"link":"https://empiali1.service-now.com/api/now/table/sys_user/6816f79cc0a8016401c5a33be04be441","value":"6816f79cc0a8016401c5a33be04be441"},"sys_updated_by":"admin","opened_by":{"link":"https://empiali1.service-now.com/api/now/table/sys_user/681ccaf9c0a8016400b98a06818d57c7","value":"681ccaf9c0a8016400b98a06818d57c7"},"user_input":"","sys_created_on":"2015-12-29 18:24:13","sys_domain":{"link":"https://empiali1.service-now.com/api/now/table/sys_user_group/global","value":"global"},"state":"7","sys_created_by":"pat","knowledge":"false","order":"","calendar_stc":"7937 oAuth client scripting This script is useful to generate access token using refresh token. //readTokenfromDB();RefreshTokenFlow();/**** requestorId is the REST's sys_id ( 22dd8a98373301006b882d465abe5d3c ) if token is generated from Outbound Rest Message.oauthProfileId is the oauth_entity_profile's sys_id ( c3d399f7dbca2300980c90b6db961990 ).This is the available in the outbound rest message. Refresh Token:lVtNy178JEvajjOIBcYqHggAHqYXhymJvuuPcuNTKBz_hsgagXH-sTmo305ycbgdwO-cBu7ADBc5djNq1j10pA ****/ function readTokenfromDB(){ var client = new sn_auth.GlideOAuthClient(); var token = client.getToken("22dd8a98373301006b882d465abe5d3c", "c3d399f7dbca2300980c90b6db961990"); dumpToken(token); function dumpToken(token) { if(token) { gs.info("Prints Glide oAuthToken Object Members"); gs.info("Access Token:" + token.getAccessToken()); gs.info("AccessTokenExpiresIn:" + token.getExpiresIn()); gs.info("Access Token SysID:" + token.getAccessTokenSysID()); gs.info("Access Token Scope:" + token.getScope()); gs.info("Refresh Token:" + token.getRefreshToken()); gs.info("Refresh Token SysID:" + token.getRefreshTokenSysID()); } }}/****This script is useful to generate a access token using refresh token. Grant Type :refresh_tokenRefresh Token :JKkitpFrVY6Zlxv2tISLvWYk1nCLLjAq69dR6FYw6O5L1mIHfrlplaMH8Zowg91ds60Xg6xl4WpfSiWdZLHqjAoAuth_client : oAuth Client is the oAuth Entity sysid ( client / consumer configurations ) ****/ function RefreshTokenFlow(){ var tokenRequest = new sn_auth.GlideOAuthClientRequest(); //var tokenRequest =new GlideOAuthClientRequest();tokenRequest.setGrantType("refresh_token");tokenRequest.setRefreshToken("lVtNy178JEvajjOIBcYqHggAHqYXhymJvuuPcuNTKBz_hsgagXH-sTmo305ycbgdwO-cBu7ADBc5djNq1j10pA");tokenRequest.setScope(null); var oAuthClient = new sn_auth.GlideOAuthClient(); //Retrieves the token for the client and the request set into a GlideOAuthClientResponse object. var tokenResponse = oAuthClient.requestTokenByRequest("pkce-consumer", tokenRequest); //Prints GlideOAuthClientResponse object. gs.info("Prints GlideOAuthClientResponse object members"); gs.info("Error:" + tokenResponse.getErrorMessage()); gs.info("Token Response Body:" + tokenResponse.getBody()); gs.info("Token Response Content Type:" + tokenResponse.getContentType()); gs.info("Token Response Code:" + tokenResponse.getResponseCode()); gs.info("Token Response Parameters:" + tokenResponse.getResponseParameters()); var paramMap = tokenResponse.getResponseParameters() gs.info("Iterating Token Response Parameters Starts"); for (param in paramMap){ gs.info("Key:"+param+" "+"value:"+paramMap[param].toString()); //paramMap.put(param, tokenResponse2[param].toString()); } gs.info("Iterating Token Response Parameters Ends"); //This Returns GlideOAuthToken object var token = tokenResponse.getToken(); dumpToken(token); } function dumpToken(token) { if(token) { gs.info("Prints Glide oAuthToken Object Members"); gs.info("AccessToken:" + token.getAccessToken()); gs.info("AccessTokenExpiresIn:" + token.getExpiresIn()); gs.info("Access Token SysID:" + token.getAccessTokenSysID()); gs.info("Access Token Scope:" + token.getScope()); } } Output: OAUTH - OAuthHTTPRequest : Sending http request, url:https://empiali1.service-now.com/oauth_token.doOUTBOUND USAGE ANALYTICS - OutboundUsageAnalytics : OutboundUsageAnalytics: Usage analytics send failed OAUTH - OAuthHTTPRequest : Sending http request, body:refresh_token=lVtNy178JEvajjOIBcYqHggAHqYXhymJvuuPcuNTKBz_hsgagXH-sTmo305ycbgdwO-cBu7ADBc5djNq1j10pA&grant_type=refresh_token&scope=null&client_secret=JUoM4%7D98P5&client_id=6d7fc937dbca2300aee69e18cf6233edSecurityUtils: Obfuscating Key : access_token and all its children!SecurityUtils: Obfuscating Key : refresh_token and all its children!OAUTH - OAuthHTTPRequest : Received http response: {"access_token":"********","refresh_token":"********","scope":"useraccount","token_type":"Bearer","expires_in":1799}*** Script: Prints GlideOAuthClientResponse object members*** Script: Error:null*** Script: Token Response Body:{"access_token":"6CAQUaYch9Iyb4tF5nuraJ0OTMmkwKBhVD18eLZIQlzsiVFy4K39E8YQfJzN_vB3whO0ZwFkWXxw_imPitgLXA","refresh_token":"lVtNy178JEvajjOIBcYqHggAHqYXhymJvuuPcuNTKBz_hsgagXH-sTmo305ycbgdwO-cBu7ADBc5djNq1j10pA","scope":"useraccount","token_type":"Bearer","expires_in":1799}*** Script: Token Response Content Type:application/json;charset=utf-8*** Script: Token Response Code:200*** Script: Token Response Parameters:[object Object]*** Script: Iterating Token Response Parameters Starts*** Script: Key:access_token value:6CAQUaYch9Iyb4tF5nuraJ0OTMmkwKBhVD18eLZIQlzsiVFy4K39E8YQfJzN_vB3whO0ZwFkWXxw_imPitgLXA*** Script: Key:refresh_token value:lVtNy178JEvajjOIBcYqHggAHqYXhymJvuuPcuNTKBz_hsgagXH-sTmo305ycbgdwO-cBu7ADBc5djNq1j10pA*** Script: Key:scope value:useraccount*** Script: Key:token_type value:Bearer*** Script: Key:expires_in value:1799*** Script: Iterating Token Response Parameters Ends*** Script: Prints Glide oAuthToken Object Members*** Script: AccessToken:6CAQUaYch9Iyb4tF5nuraJ0OTMmkwKBhVD18eLZIQlzsiVFy4K39E8YQfJzN_vB3whO0ZwFkWXxw_imPitgLXA*** Script: AccessTokenExpiresIn:1799*** Script: Access Token SysID:null*** Script: Access Token Scope:useraccountRelease Madrid and Higher release. Please check doc.servicenow.com for all the supported releases. Related LinksRFC:https://tools.ietf.org/html/rfc6749 & https://tools.ietf.org/html/rfc7636PKCE:https://oauth.net/2/pkce/oAuth 2.0:https://docs.servicenow.com/search?q=OAuth+2.0