OpenId Connect

How to use Google as OpenID Connect provider for Salesforce?

Topics

Demo

Demo oid

Auth. Provider settings

auth provide settings

Salesforce Configuration

URLLink
Test-Only Initialization URLhttps://mohansun-ea-02-dev-ed.my.salesforce.com/services/auth/test/Google
Single Sign-On Initialization URLhttps://mohansun-ea-02-dev-ed.my.salesforce.com/services/auth/sso/Google
Existing User Linking URLhttps://mohansun-ea-02-dev-ed.my.salesforce.com/services/auth/link/Google
OAuth-Only Initialization URLhttps://mohansun-ea-02-dev-ed.my.salesforce.com/services/auth/oauth/Google
Callback URLhttps://mohansun-ea-02-dev-ed.my.salesforce.com/services/authcallback/Google
Single Logout URLhttps://mohansun-ea-02-dev-ed.my.salesforce.com/services/auth/rp/oidc/logout

Google OIDC Provider Configuration

URLLink
Authorize Endpoint URLhttps://accounts.google.com/o/oauth2/auth
Token Endpoint URLhttps://accounts.google.com/o/oauth2/token
User Info Endpoint URLhttps://www.googleapis.com/oauth2/v3/userinfo

OID provider client secret details

  • Note: Content is mangled here to protect the Identity

{
  "web": {
    "project_id": "oidtest-310720",
    
    "client_id": "113225562349-fqktafcJUNK.apps.googleusercontent.com",
    "client_secret": "6VIgVAz8NlJUNKIk4INu4",

    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
   
     "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",


    "redirect_uris": [
      "https://mohansun-ea-02-dev-ed.my.salesforce.com/services/authcallback/Google"
    ]
  }
}

Sample Autocreated RegHandler class

// TODO:This autogenerated class includes the basics for a Registration

// Handler class. You will need to customize it to ensure it meets your needs and
// the data provided by the third party.

global class AutocreatedRegHandler1618428423355 implements Auth.RegistrationHandler {
   
 global boolean canCreateUser(Auth.UserData data) {
        //TODO: Check whether we want to allow creation of a user with this data
        //Set<String> s = new Set<String>{'usernamea', 'usernameb', 'usernamec'};
        //if(s.contains(data.username)) {
            //return true;
        //}
        return false;
    }

    global User createUser(Id portalId, Auth.UserData data){
        System.debug(data);       
    
        User u = [Select Id From User WHERE federationidentifier = :data.email LIMIT 1];
        return u;
    }

    global void updateUser(Id userId, Id portalId, Auth.UserData data){
         
    }


}

Querying AuthProvider


SELECT Id,authorizeUrl,
consumerKey,consumerSecret,
customMetadataTypeRecord,
defaultScopes,
DeveloperName,
errorUrl,
friendlyName,
iconUrl,
idTokenIssuer,
LinkKickoffUrl,
logoutUrl,
OauthKickoffUrl,
providerType,
tokenUrl,
userInfoUrl


FROM AuthProvider 


Log from the RegHandler

log regHandler

Metadata details of this AuthProvider

$ sfdx mohanc:mdapi:list -u mohan.chinnappan.n_ea2@gmail.com -t AuthProvider

{
  result: [
    {
      createdById: '0053h000002xQ5sAAE',
      createdByName: 'Mohan Chinnappan',
      createdDate: 2020-12-11T17:06:31.000Z,
      fileName: 'authproviders/Google.authprovider',
      fullName: 'Google',
      id: '0SO3h000000CwxxGAC',
      lastModifiedById: '0053h000002xQ5sAAE',
      lastModifiedByName: 'Mohan Chinnappan',
      lastModifiedDate: 1970-01-01T00:00:00.000Z,
      type: 'AuthProvider'
    }
  ]
}

$ sfdx mohanc:mdapi:retrieve -u mohan.chinnappan.n_ea2@gmail.com -t AuthProvider
{
    "RetrieveRequest": {
        "apiVersion": "51.0",
        "unpackaged": [
            {
                "types": {
                    "members": "*",
                    "name": "AuthProvider"
                }
            }
        ]
    }
}
{ result: { done: false, id: '09S3h000005hIRGEA2', state: 'Queued' } }
$ sfdx mohanc:mdapi:checkRetrieveStatus  -u mohan.chinnappan.n_ea2@gmail.com -i 09S3h000005hIRGEA2

[
  {
    createdById: '',
    createdByName: '',
    createdDate: 2020-12-11T17:06:31.000Z,
    fileName: 'unpackaged/authproviders/Google.authprovider',
    fullName: 'Google',
    id: '0SO3h000000CwxxGAC',
    lastModifiedById: '',
    lastModifiedByName: '',
    lastModifiedDate: 1970-01-01T00:00:00.000Z,
    type: 'AuthProvider'
  },
  {
    createdById: '0053h000002xQ5sAAE',
    createdByName: 'Mohan Chinnappan',
    createdDate: 2021-04-16T01:12:48.036Z,
    fileName: 'unpackaged/package.xml',
    fullName: 'unpackaged/package.xml',
    id: '',
    lastModifiedById: '0053h000002xQ5sAAE',
    lastModifiedByName: 'Mohan Chinnappan',
    lastModifiedDate: 2021-04-16T01:12:48.036Z,
    manageableState: 'unmanaged',
    type: 'Package'
  }
]
=== Writing zipFile base64 content to 09S3h000005hIRGEA2.zip.txt ...
=== Writing zipFile binary content to 09S3h000005hIRGEA2.zip ... 

$ jar tvf 09S3h000005hIRGEA2.zip
  1054 Fri Apr 16 01:12:48 EDT 2021 unpackaged/authproviders/Google.authprovider
   224 Fri Apr 16 01:12:48 EDT 2021 unpackaged/package.xml
$ unzip 09S3h000005hIRGEA2.zip
Archive:  09S3h000005hIRGEA2.zip
  inflating: unpackaged/authproviders/Google.authprovider  
  inflating: unpackaged/package.xml  

$ cat authproviders/Google.authprovider 
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
    <authorizeUrl>https://accounts.google.com/o/oauth2/auth</authorizeUrl>
    <consumerKey>_junk_-fqktafcmesni74spapbj1ep0pvja4oor.apps.googleusercontent.com</consumerKey>
    <consumerSecret>_____</consumerSecret>
    <defaultScopes>email openid  profile</defaultScopes>
    <executionUser>mohan.chinnappan@email.com</executionUser>
    <friendlyName>Google</friendlyName>
    <includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
    <providerType>Google</providerType>
    <registrationHandler>AutocreatedRegHandler1618428423355</registrationHandler>
    <sendAccessTokenInHeader>false</sendAccessTokenInHeader>
    <sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
    <sendSecretInApis>true</sendSecretInApis>
    <tokenUrl>https://accounts.google.com/o/oauth2/token</tokenUrl>
    <userInfoUrl>https://www.googleapis.com/oauth2/v3/userinfo</userInfoUrl>
</AuthProvider>


Test-Only Initialization URL

  • https://mohansun-ea-02-dev-ed.my.salesforce.com/services/auth/test/Google
  • Run Test Only

Getting AccessToken for the Google using Auth.AuthToken and UserInfo

// file: ~/.apex/oidc.cls 
String authProviderId = '0SO3h000000Cwxx';
String providerName = 'Google';
String accessToken = Auth.AuthToken.getAccessToken(authProviderId, providerName);
System.debug('accessToken: ' + accessToken);

# you can also use developer console to execute above apex code instead of CLI
sfdx mohanc:tooling:execute -a ~/.apex/oidc.cls -u mohan.chinnappan.n_ea2@gmail.com   
apexCode: String authProviderId = '0SO3h000000Cwxx';
String providerName = 'Google';
String accessToken = Auth.AuthToken.getAccessToken(authProviderId, providerName);
System.debug('accessToken: ' + accessToken);

compiled?: true
executed?: true
{
  line: -1,
  column: -1,
  compiled: true,
  success: true,
  compileProblem: null,
  exceptionStackTrace: null,
  exceptionMessage: null
}

Check logs

sfdx force:apex:log:list  -u mohan.chinnappan.n_ea2@gmail.com
APPLICATION DURATION (MS) ID                 LOCATION   SIZE (B) LOG USER         OPERATION                                                 REQUEST     START TIME               STATUS  
 ─────────── ───────────── ────────────────── ────────── ──────── ──────────────── ───────────────────────────────────────────────────────── ─────────── ──────────────────────── ─────── 
 Unknown     94            07L3h00000AvxqyEAB SystemLog  3640     Mohan Chinnappan /services/data/v57.0/tooling/executeAnonymous             Api         2023-04-04T05:44:30+0000 Success 

sfdx force:apex:log:get -i 07L3h00000AvxqyEAB  -u mohan.chinnappan.n_ea2@gmail.com    | grep -i Debug
57.0 APEX_CODE,FINEST;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;NBA,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,FINER;WAVE,INFO;WORKFLOW,INFO
Execute Anonymous: System.debug('accessToken: ' + accessToken);
22:44:30.1 (7497609)|USER_DEBUG|[4]|DEBUG|accessToken: ya29.a0Ael9sCNXJZqO7O34pvUcb4sDkO9S0X3hbBTxtMnnZ1H00TJQq_mhaPAR5fXffydfasdfsarerrvSneMUdC8Wen9YOHYNn4rQ1sNtiHDFQqRQ6gtqGPBdrgHFz3kBsTEobU4OP59OJSIJJ1OO1kUkaCgYKAUYSARMSFQF4udJh3LjnChU-94GnI--qgC6QcA0166

If you have used Developer Console to execute the apex code, here is the view from the Developer Console:

Access Token Google

Let us get the userInfo


# Note the accessToken used here is mangled to protect identity
curl https://www.googleapis.com/oauth2/v3/userinfo -H "Authorization: Bearer ya29.a0Ael9sCNXJZqO7O34pvUcb4sDkO9S0X3hbBTxtMnnZ1H00TJQq_mhadfdj3335fXffy4JsugBpVZSjY06npxOmlFJPvSneMUdC8Wen9YOHYNn4rQ1sNtiHDFQqRQ6gtqGPBdrgHFz3kBsTEobU4OP59OJSIJJ1OO1kUkaCgYKAUYSARMSFQF4udJh3LjnChU-94GnI--qgC6QcA0166" -X GET


{
  "sub": "102467670031694452102",
  "name": "Mohan Chinnappan",
  "given_name": "Mohan",
  "family_name": "Chinnappan",
  "picture": "https://lh3.googleusercontent.com/a/AGNmyxbp471dpjPtNSeeeejyyNbh1fFJqlknZUaDqrmb\u003ds96-c",
  "email": "mohan.chinnappan.n@gmail.com",
  "email_verified": true,
  "locale": "en"

}

Viewing RegistrationHandlerUserUpdate log

sfdx force:apex:log:list  -u mohan.chinnappan.n_ea2@gmail.com

 APPLICATION DURATION (MS) ID                 LOCATION   SIZE (B) LOG USER         OPERATION                                                 REQUEST     START TIME               STATUS  
 ─────────── ───────────── ────────────────── ────────── ──────── ──────────────── ───────────────────────────────────────────────────────── ─────────── ──────────────────────── ─────── 
 Unknown     91            07L3h00000AvxrhEAB SystemLog  6559     Mohan Chinnappan RegistrationHandlerUserUpdate                             Application 2023-04-04T10:44:35+0000 Success 


sfdx force:apex:log:get -i 07L3h00000AvxrhEAB  -u mohan.chinnappan.n_ea2@gmail.com    | grep -i Debug
03:44:35.5 (12059570)|USER_DEBUG|[25]|DEBUG|UserData:[attributeMap={email=mohan.chinnappan.n@gmail.com, email_verified=true, family_name=Chinnappan, given_name=Mohan, locale=en, name=Mohan Chinnappan, picture=https://lh3.googleusercontent.com/a/AGNmyxbp471dpjPtNSeeeejyyNbh1fFJqlknZUaDqrmb=s96-c, sub=102467670031694452102}, email=mohan.chinnappan.n@gmail.com, firstName=Mohan, fullName=Mohan Chinnappan, identifier=102467670031694452102, lastName=Chinnappan, link=null, locale=en, provider=Google, siteLoginUrl=null, username=null]

Resources

About OpenID connect

  • Simple Identity layer on top of the OAuth 2.0 protocol
  • Allows Clients (like service providers) to verify the identity of the End-User based on the authentication performed by an Authorization Server