Sample code for 30+ languages & platforms
PureBasic Requires Chilkat v11.0.0+

Validate a Google ID Token

See more OAuth2 Examples

Demonstrates how to verify the signature of a Google id token.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkHttp.pb"
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkJsonObject.pb"
IncludeFile "CkRsa.pb"
IncludeFile "CkPublicKey.pb"

Procedure ChilkatExample()

    success.i = 0

    ;  This example requires the Chilkat API to have been previously unlocked.
    ;  See Global Unlock Sample for sample code.

    http.i = CkHttp::ckCreate()
    If http.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ;  First get the public key we'll be needing..
    jwkStr.s = CkHttp::ckQuickGetStr(http,"https://www.googleapis.com/oauth2/v3/certs")
    If CkHttp::ckLastMethodSuccess(http) = 0
        Debug CkHttp::ckLastErrorText(http)
        CkHttp::ckDispose(http)
        ProcedureReturn
    EndIf

    ;  We have the following:

    ;      {
    ;        "keys": [
    ;  	{
    ;  	  "kid": "e8732db06287515556213b80acbcfd08cfb302a9",
    ;  	  "n": "4RIrO30287Wsq3gqXCMkUYMVAeI3H8...w2mbMNEBQ",
    ;  	  "kty": "RSA",
    ;  	  "e": "AQAB",
    ;  	  "alg": "RS256",
    ;  	  "use": "sig"
    ;  	},
    ;  	{
    ;  	  "kid": "8462a71da4f6d611fc0fecf0fc4ba9c37d65e6cd",
    ;  	  "e": "AQAB",
    ;  	  "n": "xT_ngLZNmT5GBtJZeTB...Ft4gK0eoFi0d3l8bcw",
    ;  	  "alg": "RS256",
    ;  	  "use": "sig",
    ;  	  "kty": "RSA"
    ;  	}
    ;        ]
    ;      }

    json.i = CkJsonObject::ckCreate()
    If json.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkJsonObject::ckLoad(json,jwkStr)

    ;  -------------------------------------------------

    ;  Load the following..

    ;   {
    ;    "access_token": "ya29.a0...0f",
    ;    "expires_in": 3599,
    ;    "scope": "openid https://www.googleapis.com/auth/userinfo.email",
    ;    "token_type": "Bearer",
    ;    "id_token": "eyJhb...o5nQ"
    ;  }

    jsonToken.i = CkJsonObject::ckCreate()
    If jsonToken.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkJsonObject::ckLoadFile(jsonToken,"qa_data/tokens/google_sample_id_token.json")
    If success = 0
        Debug "Failed to load the JSON file..."
        CkHttp::ckDispose(http)
        CkJsonObject::ckDispose(json)
        CkJsonObject::ckDispose(jsonToken)
        ProcedureReturn
    EndIf

    ;  Get the id_token;
    sbIdToken.i = CkStringBuilder::ckCreate()
    If sbIdToken.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkStringBuilder::ckAppend(sbIdToken,CkJsonObject::ckStringOf(jsonToken,"id_token"))

    ;  Get the signature in base64url format.
    ;  The header + payload remains in sbIdToken.
    sig_b64Url.s = CkStringBuilder::ckGetAfterFinal(sbIdToken,".",1)
    headerPlusPayload.s = CkStringBuilder::ckGetAsString(sbIdToken)

    Debug sig_b64Url
    Debug headerPlusPayload

    ;  ---------------------------------------------

    ;  Try validating with each cert's public key.
    ;  Hopefully one will be the key that verifies.

    rsa.i = CkRsa::ckCreate()
    If rsa.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkRsa::setCkEncodingMode(rsa, "base64url")

    jsonKey.i = CkJsonObject::ckCreate()
    If jsonKey.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    pubKey.i = CkPublicKey::ckCreate()
    If pubKey.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    numKeys.i = CkJsonObject::ckSizeOfArray(json,"keys")
    i.i = 0
    While i < numKeys
        CkJsonObject::setCkI(json, i)

        CkJsonObject::ckObjectOf2(json,"keys[i]",jsonKey)

        success = CkPublicKey::ckLoadFromString(pubKey,CkJsonObject::ckEmit(jsonKey))
        If success = 0
            Debug CkPublicKey::ckLastErrorText(pubKey)
            CkHttp::ckDispose(http)
            CkJsonObject::ckDispose(json)
            CkJsonObject::ckDispose(jsonToken)
            CkStringBuilder::ckDispose(sbIdToken)
            CkRsa::ckDispose(rsa)
            CkJsonObject::ckDispose(jsonKey)
            CkPublicKey::ckDispose(pubKey)
            ProcedureReturn
        EndIf

        Debug Str(i)
        Debug CkPublicKey::ckGetPem(pubKey,1)

        success = CkRsa::ckUsePublicKey(rsa,pubKey)

        bVerified.i = CkRsa::ckVerifyStringENC(rsa,headerPlusPayload,"sha256",sig_b64Url)
        Debug "bVerified = " + Str(bVerified)

        i = i + 1
    Wend

    ;  The output is:

    ;  0
    ;  -----BEGIN RSA PUBLIC KEY-----
    ;  MIIBCgKCAQEA4RIrO30287Wsq3gqXCMkUYMVAeI3H8LVE6IXR1krdFeGnZLiGUPw
    ;  cbkeVpXf3lmJdsStOg+jijces2DZCfPyIBiQuLYfxxmAZE6ErJ0QJFg1stwli2Pz
    ;  9ncYhFoqi8pXr7kEzEJBTzX4thuw56ydbGsshSEznPXoerCJOc7UI2+n0wFCWQ4Y
    ;  LHbh/PrWt4vdadyUUUW/QpQHXQLdD8q/Qwqdj0O9zlJE7R6Elw2E9EqnHyIGu1hm
    ;  LxhqrTru1M18SUhONYbVskV/BCEdVKs//X96849HorWQDCAgVMWfGsdMVq55FAdJ
    ;  680N5UmQDRynIZ4+PeNGN4S9iw2mbMNEBQIDAQAB
    ;  -----END RSA PUBLIC KEY-----
    ;  
    ;  bVerified = True
    ;  1
    ;  -----BEGIN RSA PUBLIC KEY-----
    ;  MIIBCgKCAQEAxT/ngLZNmT5GBdkLtJZjNeTB+8B5yWgrq/e5eMZ1hrZhcmLK+dSn
    ;  IkpOPV8/OekV67EnQ7I4II2rcNJnHGrGKZziXO3XN2gtUHE+mBJC99oULSbX/QwB
    ;  Kz7gC/IBPq9EuxTt6Oq6fPkVQ9DbRIgWJSEGBF/KRaNl3kyAlIZfpY7XgHyJTTv8
    ;  E7yAcYKPR+36gzdl+ps0sDLKzUuAtZNq8llK0u80z6AtAUIYwWdkEhM9upy6keKI
    ;  TasIxcsO7M6kZPINUSbh6t5VAm8FuqRmxpgg+9c9/GQSGd89InVypoVzWLQ+wOGg
    ;  5G4H6JqIgtj0TRFt4gK0eoFi2U0d3l8bcwIDAQAB
    ;  -----END RSA PUBLIC KEY-----
    ;  
    ;  bVerified = False


    CkHttp::ckDispose(http)
    CkJsonObject::ckDispose(json)
    CkJsonObject::ckDispose(jsonToken)
    CkStringBuilder::ckDispose(sbIdToken)
    CkRsa::ckDispose(rsa)
    CkJsonObject::ckDispose(jsonKey)
    CkPublicKey::ckDispose(pubKey)


    ProcedureReturn
EndProcedure