DataFlex
DataFlex
Uni Economy API Client Credentials Flow
See more OAuth2 Examples
Demonstrates how to do OAuth 2.0 using the client credentials flow for the Uni Economy API. (This means that the server can authenticate against the identity server without human interaction.)Chilkat DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
Handle hoCert
Variant vPrivKey
Handle hoPrivKey
Handle hoJwt
Handle hoJose
String sMyClientId
Handle hoClaims
Handle hoCrypt
Integer iCurDateTime
String sJwt_token
Handle hoHttp
Variant vResp
Handle hoResp
Handle hoJson
String sTokenEndpoint
Variant vGrantTypes
Handle hoGrantTypes
Integer iClientCredentialsIdx
Variant vReq
Handle hoReq
String sAccessToken
Variant vSbResponse
Handle hoSbResponse
String sTemp1
String sTemp2
Integer iTemp1
Move False To iSuccess
// This example requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
// Step 1 ------------------------------------------------------------------------------------------
// First create a client token...
Get Create (RefClass(cComChilkatCert)) To hoCert
If (Not(IsComObjectCreated(hoCert))) Begin
Send CreateComObject of hoCert
End
Set ComVerboseLogging Of hoCert To True
// Note: .pfx and .p12 files are identical. The only difference is the file extension.
// Also, if your .p12 password is longer than 64 chars, you'll need Chilkat v9.5.0.83 or later.
// To shorten the password, import your .p12 onto your Windows computer by double-clicking on the .p12 file,
// make sure when importing that keys are exportable, then re-export with private keys to a .pfx with a new password.
Get ComLoadPfxFile Of hoCert "qa_data/pfx/UniCert_Norge_Test_secret.pfx" "secret" To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoCert To sTemp1
Showln sTemp1
Procedure_Return
End
Get Create (RefClass(cComChilkatPrivateKey)) To hoPrivKey
If (Not(IsComObjectCreated(hoPrivKey))) Begin
Send CreateComObject of hoPrivKey
End
Get pvComObject of hoPrivKey to vPrivKey
Get ComGetPrivateKey Of hoCert vPrivKey To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoCert To sTemp1
Showln sTemp1
Procedure_Return
End
Get Create (RefClass(cComChilkatJwt)) To hoJwt
If (Not(IsComObjectCreated(hoJwt))) Begin
Send CreateComObject of hoJwt
End
// Build the JOSE header
Get Create (RefClass(cComChilkatJsonObject)) To hoJose
If (Not(IsComObjectCreated(hoJose))) Begin
Send CreateComObject of hoJose
End
// Use RS256. Pass the string "RS384" or "RS512" to use RSA with SHA-384 or SHA-512.
Get ComAppendString Of hoJose "alg" "RS256" To iSuccess
Get ComAppendString Of hoJose "typ" "JWT" To iSuccess
// Now build the JWT claims (also known as the payload)
// Our JWT claims will contain members as shown here:
// {
// "jti": "ad612fce-3e71-4f6a-8af1-7eb0414b4eea", <-- generated unique global identifier
// "sub": "99999999-aaaa-bbbb-cccc-ddddeeeeffff", <-- This is the clientId
// "iat": 1588102982, <-- These are date/time values.
// "nbf": 1588102982,
// "exp": 1588103042,
// "iss": " 99999999-aaaa-bbbb-cccc-ddddeeeeffff",
// "aud": "https://test-login.unieconomy.no/connect/token"
// }
// Use your own client ID.
Move "99999999-aaaa-bbbb-cccc-ddddeeeeffff" To sMyClientId
Get Create (RefClass(cComChilkatJsonObject)) To hoClaims
If (Not(IsComObjectCreated(hoClaims))) Begin
Send CreateComObject of hoClaims
End
Get Create (RefClass(cComChilkatCrypt2)) To hoCrypt
If (Not(IsComObjectCreated(hoCrypt))) Begin
Send CreateComObject of hoCrypt
End
Get ComGenerateUuid Of hoCrypt To sTemp1
Get ComAppendString Of hoClaims "jti" sTemp1 To iSuccess
Get ComAppendString Of hoClaims "sub" sMyClientId To iSuccess
// Set the timestamp of when the JWT was created to now minus 60 seconds
Get ComGenNumericDate Of hoJwt -60 To iCurDateTime
Get ComAddIntAt Of hoClaims -1 "iat" iCurDateTime To iSuccess
// Set the "not process before" timestamp to now minus 60 seconds
Get ComAddIntAt Of hoClaims -1 "nbf" iCurDateTime To iSuccess
// Set the timestamp defining an expiration time (end time) for the token
// to be now + 1 hour (3600 seconds)
Get ComAddIntAt Of hoClaims -1 "exp" (iCurDateTime + 3600) To iSuccess
Get ComAppendString Of hoClaims "iss" sMyClientId To iSuccess
Get ComAppendString Of hoClaims "aud" "https://test-login.unieconomy.no/connect/token" To iSuccess
// Produce the smallest possible JWT:
Set ComAutoCompact Of hoJwt To True
// Create the JWT token. This is where the RSA signature is created.
Get ComEmit Of hoJose To sTemp1
Get ComEmit Of hoClaims To sTemp2
Get pvComObject of hoPrivKey to vPrivKey
Get ComCreateJwtPk Of hoJwt sTemp1 sTemp2 vPrivKey To sJwt_token
Showln sJwt_token
// Step 2 ------------------------------------------------------------------------------------------
Get Create (RefClass(cComChilkatHttp)) To hoHttp
If (Not(IsComObjectCreated(hoHttp))) Begin
Send CreateComObject of hoHttp
End
// Fetch the discovery document...
Get Create (RefClass(cComChilkatHttpResponse)) To hoResp
If (Not(IsComObjectCreated(hoResp))) Begin
Send CreateComObject of hoResp
End
Get pvComObject of hoResp to vResp
Get ComHttpNoBody Of hoHttp "GET" "https://test-login.unieconomy.no/.well-known/openid-configuration" vResp To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoHttp To sTemp1
Showln sTemp1
Procedure_Return
End
Get ComStatusCode Of hoResp To iTemp1
If (iTemp1 <> 200) Begin
Get ComStatusCode Of hoResp To iTemp1
Showln "Received response status code " iTemp1
Showln "Response body containing error text or JSON:"
Get ComBodyStr Of hoResp To sTemp1
Showln sTemp1
Procedure_Return
End
Get Create (RefClass(cComChilkatJsonObject)) To hoJson
If (Not(IsComObjectCreated(hoJson))) Begin
Send CreateComObject of hoJson
End
Get ComBodyStr Of hoResp To sTemp1
Get ComLoad Of hoJson sTemp1 To iSuccess
Set ComEmitCompact Of hoJson To False
Get ComEmit Of hoJson To sTemp1
Showln sTemp1
// We have the discovery document, which contains something like this:
// You can use this online tool to generate parsing code from sample JSON:
// Generate Parsing Code from JSON
// {
// "issuer": "https://test-login.unieconomy.no",
// "jwks_uri": "https://test-login.unieconomy.no/.well-known/openid-configuration/jwks",
// "authorization_endpoint": "https://test-login.unieconomy.no/connect/authorize",
// "token_endpoint": "https://test-login.unieconomy.no/connect/token",
// "userinfo_endpoint": "https://test-login.unieconomy.no/connect/userinfo",
// "end_session_endpoint": "https://test-login.unieconomy.no/connect/endsession",
// "check_session_iframe": "https://test-login.unieconomy.no/connect/checksession",
// "revocation_endpoint": "https://test-login.unieconomy.no/connect/revocation",
// "introspection_endpoint": "https://test-login.unieconomy.no/connect/introspect",
// "device_authorization_endpoint": "https://test-login.unieconomy.no/connect/deviceauthorization",
// "frontchannel_logout_supported": true,
// "frontchannel_logout_session_supported": true,
// "backchannel_logout_supported": true,
// "backchannel_logout_session_supported": true,
// "scopes_supported": [
// "openid",
// "profile",
// "email",
// "offline_access",
// "AppFramework.All",
// "AppFramework",
// "AppFramework.Sales",
// "IdentityAPI",
// "widgetApi",
// "TestScope.test",
// "TestScope.Cars",
// "HaglandAPI",
// "LicenseAdmin",
// "LicenseAdmin.Product.Read",
// "SoftRig.Product.Write",
// "TestAPI.test",
// "offline_access"
// ],
// "claims_supported": [
// "sub",
// "updated_at",
// "name",
// "family_name",
// "given_name",
// "middle_name",
// "nickname",
// "preferred_username",
// "picture",
// "website",
// "gender",
// "birthdate",
// "zoneinfo",
// "locale",
// "profile",
// "email",
// "email_verified"
// ],
// "grant_types_supported": [
// "authorization_code",
// "client_credentials",
// "refresh_token",
// "implicit",
// "password",
// "urn:ietf:params:oauth:grant-type:device_code",
// "delegation"
// ],
// "response_types_supported": [
// "code",
// "token",
// "id_token",
// "id_token token",
// "code id_token",
// "code token",
// "code id_token token"
// ],
// "response_modes_supported": [
// "form_post",
// "query",
// "fragment"
// ],
// "token_endpoint_auth_methods_supported": [
// "client_secret_basic",
// "client_secret_post",
// "private_key_jwt",
// "private_key_jwt"
// ],
// "id_token_signing_alg_values_supported": [
// "RS256"
// ],
// "subject_types_supported": [
// "public"
// ],
// "code_challenge_methods_supported": [
// "plain",
// "S256"
// ],
// "request_parameter_supported": true
// }
// ------------------------------------------------------
// The next steps are to (1) get the token_endpoint,
// and (2) verify that the client_credentials grant type is supported.
Get ComStringOf Of hoJson "token_endpoint" To sTokenEndpoint
Get ComArrayOf Of hoJson "grant_types_supported" To vGrantTypes
If (IsComObject(vGrantTypes)) Begin
Get Create (RefClass(cComChilkatJsonArray)) To hoGrantTypes
Set pvComObject Of hoGrantTypes To vGrantTypes
End
Get ComFindString Of hoGrantTypes "client_credentials" True To iClientCredentialsIdx
Send Destroy of hoGrantTypes
// If clientCredentialsIdx is less then zero (-1) then the "client_credentials" string was not found.
If (iClientCredentialsIdx < 0) Begin
Showln "The client credentials grant type is not supported."
Procedure_Return
End
// ------------------------------------------------------
// Request the access token using our Client ID and JWT
Get Create (RefClass(cComChilkatHttpRequest)) To hoReq
If (Not(IsComObjectCreated(hoReq))) Begin
Send CreateComObject of hoReq
End
Set ComHttpVerb Of hoReq To "POST"
Set ComContentType Of hoReq To "application/x-www-form-urlencoded"
Send ComAddParam To hoReq "client_id" sMyClientId
Send ComAddParam To hoReq "scope" "AppFramework.Sales"
Send ComAddParam To hoReq "grant_type" "client_credentials"
Send ComAddParam To hoReq "client_assertion_type" "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
Send ComAddParam To hoReq "client_assertion" sJwt_token
Get pvComObject of hoReq to vReq
Get pvComObject of hoResp to vResp
Get ComHttpReq Of hoHttp sTokenEndpoint vReq vResp To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoHttp To sTemp1
Showln sTemp1
Procedure_Return
End
// Make sure we got a 200 response status code, otherwise it's an error.
Get ComStatusCode Of hoResp To iTemp1
If (iTemp1 <> 200) Begin
Showln "POST to token endpoint failed."
Get ComStatusCode Of hoResp To iTemp1
Showln "Received response status code " iTemp1
Showln "Response body containing error text or JSON:"
Get ComBodyStr Of hoResp To sTemp1
Showln sTemp1
Procedure_Return
End
Get ComBodyStr Of hoResp To sTemp1
Get ComLoad Of hoJson sTemp1 To iSuccess
Get ComEmit Of hoJson To sTemp1
Showln sTemp1
// The JSON response will look like this:
// {
// "access_token": "...",
// "expires_in": 3600,
// "token_type": "Bearer",
// "scope": "AppFramework.Sales"
// }
// Get the access token:
Get ComStringOf Of hoJson "access_token" To sAccessToken
Showln "accessToken = " sAccessToken
// ------------------------------------------------------
// Use the access token in a request.
// We'll just send a GET request to https://test.unieconomy.no/api/init/companies
// Tell the http object to use the OAuth2 access token in the "Authorization: Bearer ..." header.
Set ComAuthToken Of hoHttp To sAccessToken
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbResponse
If (Not(IsComObjectCreated(hoSbResponse))) Begin
Send CreateComObject of hoSbResponse
End
Get pvComObject of hoSbResponse to vSbResponse
Get ComQuickGetSb Of hoHttp "https://test.unieconomy.no/api/init/companies" vSbResponse To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoHttp To sTemp1
Showln sTemp1
Procedure_Return
End
// Examine the response status code.
Get ComLastStatus Of hoHttp To iTemp1
If (iTemp1 <> 200) Begin
Get ComGetAsString Of hoSbResponse To sTemp1
Showln sTemp1
Get ComLastStatus Of hoHttp To iTemp1
Showln "response status: " iTemp1
Showln "Received error response."
Procedure_Return
End
Get pvComObject of hoSbResponse to vSbResponse
Get ComLoadSb Of hoJson vSbResponse To iSuccess
Get ComEmit Of hoJson To sTemp1
Showln sTemp1
Showln "Success."
End_Procedure