Sample code for 30+ languages & platforms
PureBasic

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