Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(DataFlex) Azure OpenID Connect Step 2 -- Get id_token and ValidateSee more OIDC ExamplesAfter getting the endpoints by querying the Azure's OIDC well-known discovery document (OpenID Configuration document), we use the authorization_endpoint to get the id_token, and then validate it.. For more information, see https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc
Use ChilkatAx-win32.pkg Procedure Test Boolean iSuccess String sAuthorization_endpoint String sJwks_uri Handle hoReq Handle hoPrng String sEncodedParams Handle hoSbUrl String sUrl Handle hoListenSock Integer iBackLog Integer iMaxWaitMs Variant vTask Handle hoTask Handle hoSock String sStartLine String sRequestHeader Variant vSbRequestBody Handle hoSbRequestBody Variant vSbResponseHtml Handle hoSbResponseHtml Handle hoSbResponse Handle hoHashTab String sIdToken Handle hoJwt Integer iLeeway Boolean iBTimeValid String sPayload Handle hoJson String sJoseHeader Handle hoJsonJoseHeader Variant vSbJwks Handle hoSbJwks Handle hoHttp Handle hoJwkset String sKid Variant vJwk Handle hoJwk Boolean iVerified Variant vPubkey Handle hoPubkey String sTemp1 Integer iTemp1 Boolean bTemp1 // This example requires the Chilkat API to have been previously unlocked. // See Global Unlock Sample for sample code. // In our previous example (Azure Fetch OpenID Connect metadata document) we fetched // the OpenID configuration document which is JSON which contains an entry for authorization_endpoint. Move "https://login.microsoftonline.com/6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd/oauth2/v2.0/authorize" To sAuthorization_endpoint // The OpenID Connect metadata document also contained a jwks_uri entry. This is the JSON Web Key Set (JWKS), // which is a set of keys containing the public keys used to verify any JSON Web Token (JWT) (in this case the id_token) // issued by the authorization server and signed using the RS256 signing algorithm. Move "https://login.microsoftonline.com/6d8ddd66-68d1-44b0-af5c-e31b4b7ee5cd/discovery/v2.0/keys" To sJwks_uri // We're going to send the following GET request, but it will be sent through an interactive web browser (not by Chilkat). // The following code will form the URL that is to be programmatically loaded and sent in a browser. // GET https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize? // client_id=6731de76-14a6-49ae-97bc-6eba6914391e // &response_type=id_token // &redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F // &response_mode=form_post // &scope=openid // &state=12345 // &nonce=678910 // Use this object to set params and then get the URL-encoded query params string Get Create (RefClass(cComChilkatHttpRequest)) To hoReq If (Not(IsComObjectCreated(hoReq))) Begin Send CreateComObject of hoReq End Send ComAddParam To hoReq "client_id" "f125d695-c50e-456e-a579-a486f06d1213" Send ComAddParam To hoReq "response_type" "id_token" Send ComAddParam To hoReq "redirect_uri" "http://localhost:3017/" Send ComAddParam To hoReq "response_mode" "form_post" Send ComAddParam To hoReq "scope" "openid" Get Create (RefClass(cComChilkatPrng)) To hoPrng If (Not(IsComObjectCreated(hoPrng))) Begin Send CreateComObject of hoPrng End Get ComGenRandom Of hoPrng 3 "decimal" To sTemp1 Send ComAddParam To hoReq "state" sTemp1 Get ComGenRandom Of hoPrng 4 "decimal" To sTemp1 Send ComAddParam To hoReq "nonce" sTemp1 Get ComGetUrlEncodedParams Of hoReq To sEncodedParams Showln sEncodedParams // Sample URL encoded params: // client_id=6731de76-14a6-49ae-97bc-6eba6914391e&redirect_uri=http%3A%2F%2Flocalhost%3A3017%2F&response_mode=form_post&scope=openid&state=3572902&nonce=57352474 // This is the URL to be programmatically loaded and sent in an interactive web browser.. Get Create (RefClass(cComChilkatStringBuilder)) To hoSbUrl If (Not(IsComObjectCreated(hoSbUrl))) Begin Send CreateComObject of hoSbUrl End Get ComAppend Of hoSbUrl sAuthorization_endpoint To iSuccess Get ComAppend Of hoSbUrl "?" To iSuccess Get ComAppend Of hoSbUrl sEncodedParams To iSuccess Get ComGetAsString Of hoSbUrl To sUrl // Before we launch the browser with the contents of sbUrl, create a socket to listen for the eventual callback.. Get Create (RefClass(cComChilkatSocket)) To hoListenSock If (Not(IsComObjectCreated(hoListenSock))) Begin Send CreateComObject of hoListenSock End // Listen at the port indicated by the redirect_uri above. Move 5 To iBackLog Get ComBindAndListen Of hoListenSock 3017 iBackLog To iSuccess If (iSuccess <> True) Begin Get ComLastErrorText Of hoListenSock To sTemp1 Showln sTemp1 Procedure_Return End // Wait for the browser's connection in a background thread. // (We'll send load the URL into the browser following this..) // Wait a max of 60 seconds before giving up. Move 60000 To iMaxWaitMs Get ComAcceptNextConnectionAsync Of hoListenSock iMaxWaitMs To vTask If (IsComObject(vTask)) Begin Get Create (RefClass(cComChilkatTask)) To hoTask Set pvComObject Of hoTask To vTask End Get ComRun Of hoTask To iSuccess // ------------------------------------------------------------------- // At this point, your application should load the URL in a browser. // You'll need to add code here to do it.. // For example, // in C#: System.Diagnostics.Process.Start(url); // in Java: Desktop.getDesktop().browse(new URI(url)); // in VBScript: Set wsh=WScript.CreateObject("WScript.Shell") // wsh.Run url // in Xojo: ShowURL(url) (see http://docs.xojo.com/index.php/ShowURL) // in Dataflex: Runprogram Background "c:\Program Files\Internet Explorer\iexplore.exe" sUrl // The account owner would interactively accept or deny the authorization request. // Add the code to load the url in a web browser here... // Add the code to load the url in a web browser here... // Add the code to load the url in a web browser here... // System.Diagnostics.Process.Start(url); // ------------------------------------------------------------------- // Wait for the listenSock's task to complete. Get ComWait Of hoTask iMaxWaitMs To iSuccess Get ComStatusInt Of hoTask To iTemp1 Get ComTaskSuccess Of hoTask To bTemp1 If (Not iSuccess Or (iTemp1 <> 7) Or (bTemp1 <> True)) Begin If (Not iSuccess) Begin // The task.LastErrorText applies to the Wait method call. Get ComLastErrorText Of hoTask To sTemp1 Showln sTemp1 End Else Begin // The ResultErrorText applies to the underlying task method call (i.e. the AcceptNextConnection) Get ComStatus Of hoTask To sTemp1 Showln sTemp1 Get ComResultErrorText Of hoTask To sTemp1 Showln sTemp1 End Send Destroy of hoTask Procedure_Return End // If we get to this point, a connection on listenSock was accepted, and the redirected POST // is waiting to be read on the connected socket. // The POST we are going to read contains the following: // POST /myapp/ HTTP/1.1 // Host: localhost // Content-Type: application/x-www-form-urlencoded // // id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNB...&state=12345 // But first.. we no longer need the listen socket... // Stop listening on port 3017. Get ComClose Of hoListenSock 10 To iSuccess // Get the connected socket. Get Create (RefClass(cComChilkatSocket)) To hoSock If (Not(IsComObjectCreated(hoSock))) Begin Send CreateComObject of hoSock End Get ComLoadTaskResult Of hoSock vTask To iSuccess Send Destroy of hoTask // We're acting as a temporary web server to receive this one redirected HTTP request.. // Read the start line of the request.. (i.e. the "POST /myapp/ HTTP/1.1") Get ComReceiveUntilMatch Of hoSock (character(13)) + (character(10)) To sStartLine Get ComLastMethodSuccess Of hoSock To bTemp1 If (bTemp1 <> True) Begin Get ComLastErrorText Of hoSock To sTemp1 Showln sTemp1 Procedure_Return End // Read the request header. Get ComReceiveUntilMatch Of hoSock (character(13)) + (character(10)) + (character(13)) + (character(10)) To sRequestHeader Get ComLastMethodSuccess Of hoSock To bTemp1 If (bTemp1 <> True) Begin Get ComLastErrorText Of hoSock To sTemp1 Showln sTemp1 Procedure_Return End Showln sRequestHeader Showln "----" // Read the body. // The body will contain "id_token= eyJ......" Get Create (RefClass(cComChilkatStringBuilder)) To hoSbRequestBody If (Not(IsComObjectCreated(hoSbRequestBody))) Begin Send CreateComObject of hoSbRequestBody End Get pvComObject of hoSbRequestBody to vSbRequestBody Get ComReceiveSb Of hoSock vSbRequestBody To iSuccess If (iSuccess = False) Begin Get ComLastErrorText Of hoSock To sTemp1 Showln sTemp1 Procedure_Return End Get ComGetAsString Of hoSbRequestBody To sTemp1 Showln sTemp1 // Given that we're acting as a web server, we must send a response.. // We can now send our HTTP response. Get Create (RefClass(cComChilkatStringBuilder)) To hoSbResponseHtml If (Not(IsComObjectCreated(hoSbResponseHtml))) Begin Send CreateComObject of hoSbResponseHtml End Get ComAppend Of hoSbResponseHtml "<html><body><p>Thank you!</b></body</html>" To iSuccess Get Create (RefClass(cComChilkatStringBuilder)) To hoSbResponse If (Not(IsComObjectCreated(hoSbResponse))) Begin Send CreateComObject of hoSbResponse End Get ComAppend Of hoSbResponse "HTTP/1.1 200 OK" + (character(13)) + (character(10)) To iSuccess Get ComAppend Of hoSbResponse "Content-Length: " To iSuccess Get ComLength Of hoSbResponseHtml To iTemp1 Get ComAppendInt Of hoSbResponse iTemp1 To iSuccess Get ComAppend Of hoSbResponse (character(13)) + (character(10)) To iSuccess Get ComAppend Of hoSbResponse "Content-Type: text/html" + (character(13)) + (character(10)) To iSuccess Get ComAppend Of hoSbResponse (character(13)) + (character(10)) To iSuccess Get pvComObject of hoSbResponseHtml to vSbResponseHtml Get ComAppendSb Of hoSbResponse vSbResponseHtml To iSuccess Get ComGetAsString Of hoSbResponse To sTemp1 Get ComSendString Of hoSock sTemp1 To iSuccess Get ComClose Of hoSock 50 To iSuccess // Get the id_token from the sbRequestBody that we just received. // (Remember, we're acting as the web server, thus we received the redirect request..) Get Create (RefClass(cComChilkatHashtable)) To hoHashTab If (Not(IsComObjectCreated(hoHashTab))) Begin Send CreateComObject of hoHashTab End Get ComGetAsString Of hoSbRequestBody To sTemp1 Get ComAddQueryParams Of hoHashTab sTemp1 To iSuccess // See https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens#validating-an-id-token // for more information about ID tokens.. Get ComLookupStr Of hoHashTab "id_token" To sIdToken Get Create (RefClass(cComChilkatJwt)) To hoJwt If (Not(IsComObjectCreated(hoJwt))) Begin Send CreateComObject of hoJwt End // Let's see if the time constraints, if any, are valid. // The above JWT was created on the afternoon of 16-May-2016, with an expiration of 1 hour. // If the current system time is before the "nbf" time, or after the "exp" time, // then IsTimeValid will return false/0. // Also, we'll allow a leeway of 60 seconds to account for any clock skew. // Note: If the token has no "nbf" or "exp" claim fields, then IsTimeValid is always true. Move 60 To iLeeway Get ComIsTimeValid Of hoJwt sIdToken iLeeway To iBTimeValid Showln "time constraints valid: " iBTimeValid // Now let's recover the original claims JSON (the payload). Get ComGetPayload Of hoJwt sIdToken To sPayload // The payload will likely be in compact form: Showln sPayload // We can format for human viewing by loading it into Chilkat's JSON object // and emit. Get Create (RefClass(cComChilkatJsonObject)) To hoJson If (Not(IsComObjectCreated(hoJson))) Begin Send CreateComObject of hoJson End Get ComLoad Of hoJson sPayload To iSuccess Set ComEmitCompact Of hoJson To False Get ComEmit Of hoJson To sTemp1 Showln sTemp1 // Sample output: // { // "aud": "f125d695-c50e-456e-a579-a486f06d1213", // "iss": "https://login.microsoftonline.com/6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd/v2.0", // "iat": 1626535322, // "nbf": 1626535322, // "exp": 1626539222, // "aio": "AWQAm/8TAAAAHQncmY0VvhgyMIhfleHX3DjsGfmlPM1CopkJ3mPnBUnCxrJ0ubruaACEhwGO7NsoHBhqFEzRzPxOq7MtuGVFsql+qJKZx8vQCszKYEPX9Wb3b5+d5KJTABHCIH48bTFd", // "idp": "https://sts.windows.net/9188040d-6c67-4c5b-b112-36a304b66dad/", // "nonce": "1519043321", // "rh": "0.ARgAZt2NbdFosEOvXOMbS33VzZXWJfEOxW5FpXmkhvBtEhMYALQ.", // "sub": "RMIZlHJ7hfsJmL8Qq3h6M0nPi4g-HEavnAFgxzaT2KM", // "tid": "6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd", // "uti": "-BXGHxvfREW-r9HI5NBiAA", // "ver": "2.0" // } // We can recover the original JOSE header in the same way: Get ComGetHeader Of hoJwt sIdToken To sJoseHeader // The payload will likely be in compact form: Showln sJoseHeader // We can format for human viewing by loading it into Chilkat's JSON object // and emit. Get Create (RefClass(cComChilkatJsonObject)) To hoJsonJoseHeader If (Not(IsComObjectCreated(hoJsonJoseHeader))) Begin Send CreateComObject of hoJsonJoseHeader End Get ComLoad Of hoJsonJoseHeader sJoseHeader To iSuccess Set ComEmitCompact Of hoJsonJoseHeader To False Get ComEmit Of hoJsonJoseHeader To sTemp1 Showln sTemp1 // Sample output: // { // "typ": "JWT", // "alg": "RS256", // "kid": "nOo3ZDrODXEK1jKWhXslHR_KXEg" // } // Finally, we need to fetch the JSON Web Key Sets from the jwks_uri // and use it to verify the id_token's RSA signature. Get Create (RefClass(cComChilkatStringBuilder)) To hoSbJwks If (Not(IsComObjectCreated(hoSbJwks))) Begin Send CreateComObject of hoSbJwks End Get Create (RefClass(cComChilkatHttp)) To hoHttp If (Not(IsComObjectCreated(hoHttp))) Begin Send CreateComObject of hoHttp End Get pvComObject of hoSbJwks to vSbJwks Get ComQuickGetSb Of hoHttp sJwks_uri vSbJwks To iSuccess If (iSuccess = False) Begin Get ComLastErrorText Of hoHttp To sTemp1 Showln sTemp1 Procedure_Return End Get Create (RefClass(cComChilkatJsonObject)) To hoJwkset If (Not(IsComObjectCreated(hoJwkset))) Begin Send CreateComObject of hoJwkset End Get pvComObject of hoSbJwks to vSbJwks Get ComLoadSb Of hoJwkset vSbJwks To iSuccess Set ComEmitCompact Of hoJwkset To False Get ComEmit Of hoJwkset To sTemp1 Showln sTemp1 // A sample jwkset: // { // "keys": [ // { // "kty": "RSA", // "use": "sig", // "kid": "nOo3ZDrODXEK1jKWhXslHR_KXEg", // "x5t": "nOo3ZDrODXEK1jKWhXslHR_KXEg", // "n": "oaLLT9hkcSj ... NVrZdUdTBQ", // "e": "AQAB", // "x5c": [ // "MIIDBTC ... MRku44Dw7R" // ], // "issuer": "https://login.microsoftonline.com/6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd/v2.0" // }, // { // "kty": "RSA", // "use": "sig", // "kid": "l3sQ-50cCH4xBVZLHTGwnSR7680", // "x5t": "l3sQ-50cCH4xBVZLHTGwnSR7680", // "n": "sfsXMXW ... AYkwb6xUQ", // "e": "AQAB", // "x5c": [ // "MIIDBTCCA ... BWrh+/vJ" // ], // "issuer": "https://login.microsoftonline.com/6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd/v2.0" // }, // { // "kty": "RSA", // "use": "sig", // "kid": "DqUu8gf-nAgcyjP3-SuplNAXAnc", // "x5t": "DqUu8gf-nAgcyjP3-SuplNAXAnc", // "n": "1n7-nWSL ... V3pFWhQ", // "e": "AQAB", // "x5c": [ // "MIIC8TC ... 9pIcnkPQ==" // ], // "issuer": "https://login.microsoftonline.com/6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd/v2.0" // }, // { // "kty": "RSA", // "use": "sig", // "kid": "OzZ5Dbmcso9Qzt2ModGmihg30Bo", // "x5t": "OzZ5Dbmcso9Qzt2ModGmihg30Bo", // "n": "01re9a2BU ... 5OzQ6Q", // "e": "AQAB", // "x5c": [ // "MIIC8TC ... YmwJ6sDdRvQ==" // ], // "issuer": "https://login.microsoftonline.com/6d8ddd66-68d1-43b0-af5c-e31b4b7dd5cd/v2.0" // } // ] // } // We should have an RSA key with kid matching the kid from the joseHeader.. Get ComStringOf Of hoJsonJoseHeader "kid" To sKid // Find the RSA key with the specified key id Get ComFindRecord Of hoJwkset "keys" "kid" sKid True To vJwk If (IsComObject(vJwk)) Begin Get Create (RefClass(cComChilkatJsonObject)) To hoJwk Set pvComObject Of hoJwk To vJwk End Get ComLastMethodSuccess Of hoJwkset To bTemp1 If (bTemp1 = False) Begin Showln "Failed to find a matching RSA key in the JWK key set..." Procedure_Return End Get Create (RefClass(cComChilkatPublicKey)) To hoPubkey If (Not(IsComObjectCreated(hoPubkey))) Begin Send CreateComObject of hoPubkey End Get ComEmit Of hoJwk To sTemp1 Get ComLoadFromString Of hoPubkey sTemp1 To iSuccess If (iSuccess = False) Begin Get ComLastErrorText Of hoPubkey To sTemp1 Showln sTemp1 Get ComEmit Of hoJwk To sTemp1 Showln sTemp1 End Else Begin Get pvComObject of hoPubkey to vPubkey Get ComVerifyJwtPk Of hoJwt sIdToken vPubkey To iVerified Showln "Verified: " iVerified End Send Destroy of hoJwk End_Procedure |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.