Tech Articles


Implementing OAuth 2.0 Authorization with PowerBuilder 2019 R2


Introduction

PowerBuilder supports getting secured data from the OAuth 2.0 authorization server. The Bearer access token is supported, and the following grant types are supported:

  • Authorization Code
  • Implicit Flow
  • Client Credentials
  • Extension (or Refresh Token)
  • Resource Owner Password

This document provides an example on how to set up OAuth 2.0 authorization workflow using the Authorization Code grant type in a PowerBuilder application.

Prerequisties

  • PowerBuilder 2019 R2 or above

PowerBuilder 2019 R2 has the WebBrowser control for loading the authorization page to get the authorization code; and also the OAuthClient object for obtaining the access token and the protected resource.

This is the sample PowerBuilder application. It contains two targets:

 

The oauth_code application applies the OAuth 2.0 authorization workflow using Authorization Code , which will be explained in more details in this document.

The oauth_token application applies the OAuth 2.0 authorization workflow using Implicit Flow. For supporting instructions, please refer to the Supporting OAuth 2.0 Authorization Server section in Application Techniques in the PowerBuilder documentation.

  • Setting up the authorization credential in an OAuth Server.

If you follow the instructions at Appendix: Creating a YouTube Data API to create the authorization credential for accessing Google YouTube data APIs, you will have the following authorization credential information prepared:

Implementing OAuth 2.0 Authorization

Take the following steps to learn how to implement the Authorization Code grant type (granttype = "authorization_code") in the PowerBuilder application.

Step 1: Open the demo application oauth_code_token in PowerBuilder.

Step 2: Ask the user to specify the authorization code details in the authorization_code tab of the w_oauth_code window.

Step 3: Open the WebBrowser control using OpenWithParm in the Clicked event of the GetToken button, with the authorization URL passed in the OpenWithParm parameter.

ls_Url_code = "https://accounts.google.com/o/oauth2/auth?client_id=" + ls_id + "&redirect_uri=" + ls_redirect +"&scope=" + ls_Scope + "&response_type=code"

OpenWithParm (w_webbrowser, ls_Url_code) //via the WebBrowser control

ls_code = Message.Stringparm

 Step 4: Get the access token using the authorization code via OAuthClient.

ltr_Request.tokenlocation = "https://accounts.google.com/o/oauth2/token"

ltr_Request.Method = "POST"

ltr_Request.granttype = "authorization_code"

ltr_Request.clientid = ls_id

ltr_Request.clientsecret = ls_secret

ltr_Request.ClearParams()

ltr_Request.AppendParam( "grant_type", "authorization_code")

ltr_Request.AppendParam( "client_id", ls_id )

ltr_Request.AppendParam( "client_secret", ls_secret )

ltr_Request.AppendParam( "scope", ls_Scope )

ltr_Request.AppendParam( "code", ls_code )

ltr_Request.AppendParam( "redirect_uri", ls_Redirect )

ltr_Request.ClearHeaders()

ltr_Request.SetHeader("Content-Type", "application/x-www-form-urlencoded")

 

li_rtn = loa_Client.AccessToken( ltr_Request, ltr_Response )

Step 5: Get the resource from the resource URL via the access token.

OAuthRequest loa_Request

ResourceResponse lrr_Response

loa_Request.SetAccessToken (access_token)

loa_Request.Method = "GET"

loa_Request.Url = "https://www.googleapis.com/oauth2/v1/tokeninfo"

li_rtn = ioa_Client.requestresource( loa_Request, lrr_Response )

The complete code example is as below:

String ls_id, ls_secret, ls_Scope, ls_Redirect

String ls_Body, ls_code, ls_Url_code, ls_AccessToken

Integer li_rtn

OAuthClient loa_Client

TokenRequest ltr_Request

TokenResponse ltr_Response

OAuthRequest loa_Request

ResourceResponse lrr_Response

CoderObject lco_Code

Blob lb_data

 

lco_Code = Create CoderObject

loa_Client = Create OAuthClient

 

ls_id = "434849452875-6905f1g9rjiargcnqut06afmnn0b0fp7.apps.googleusercontent.com"

ls_secret = "E1b7RsBxZWKq_yrl-kbfONF5"

ls_Scope = "https://www.googleapis.com/auth/youtube"

ls_Redirect = "https://www.appeon.com/callback"

 

//Step 1: Get the authorization code

ls_Url_code = "https://accounts.google.com/o/oauth2/auth?client_id=" + ls_id + "&redirect_uri=" + ls_Redirect +"&scope=" + ls_Scope + "&response_type=code"

OpenWithParm ( w_webbrowser,ls_Url_code )

ls_code = Message.Stringparm

If Len ( ls_code ) < 1 Then Return

If Pos( ls_code, "code=" ) < 0 Then return

ls_code = Mid ( ls_code, pos(ls_code,"=") + 1)

ls_code = Mid ( ls_code, 1, pos(ls_code,"&") - 1)

lb_data = lco_Code.Urldecode( ls_code)

ls_code = String ( lb_data,EncodingANSI!)

 

//Step 2: Get the RESTful Server token

ltr_Request.tokenlocation = "https://accounts.google.com/o/oauth2/token"

ltr_Request.Method = "POST"

ltr_Request.granttype = "authorization_code"

ltr_Request.clientid = ls_id

ltr_Request.clientsecret = ls_secret

ltr_Request.ClearParams()

ltr_Request.AppendParam( "grant_type","authorization_code")

ltr_Request.AppendParam( "client_id", ls_id )

ltr_Request.AppendParam( "client_secret", ls_secret )

ltr_Request.AppendParam( "scope", ls_Scope )

ltr_Request.AppendParam( "code", ls_code )

ltr_Request.AppendParam( "redirect_uri", ls_Redirect )

ltr_Request.ClearHeaders()

ltr_Request.SetHeader("Content-Type","application/x-www-form-urlencoded")

 

li_rtn = loa_Client.AccessToken( ltr_Request, ltr_Response )

If li_rtn = 1 Then

 ls_AccessToken = ltr_Response.GetAccessToken ( )

 //Step 3: Get the RESTful Server resource

 If Len(ls_AccessToken) > 0 Then

  loa_Request.SetAccessToken (ls_AccessToken)

  loa_Request.Method = "GET"

  loa_Request.Url = "https://www.googleapis.com/oauth2/v1/tokeninfo"

  li_rtn = loa_Client.requestresource( loa_Request, lrr_Response )

  If li_rtn = 1 Then

   lrr_Response.GetBody(ls_Body)

   MessageBox ( "Tips", ls_Body )

  End If

 

 End If

End If

Appendix: Creating a YouTube Data API

The following steps demonstrate how to create a YouTube Data API which can be used later to implement the Google OAuth server authorization code in the PowerBuilder application.

1.  Visit https://developers.google.com and select Products -> YouTube.

 

2.  Select Guides, and then select YouTube Data API (v3).

 

3.  Read the Overview section and follow its instructions to access the API Console.

 

4.  From Google APIs, create a new project or select an existing one.

 

5.  In OAuth consent screen for the project, set Application type to Public, fill in Application name and then click Save.

 

6.  Select Create Credentials -> OAuth client ID, and then set Application type to Web Application and fill in Name.

You will see Client ID and Client Secret when creation is successful. Save your Client ID and Client Secret for use later.

 

In this example, the following Client ID and Client Secret are generated:

Client ID: 434849452875-6905f1g9rjiargcnqut06afmnn0b0fp7.apps.googleusercontent.com

Client Secret: E1b7RsBxZWKq_yrl-kbfONF5

7.  Click the OAuth Client you created in step 6, and then set URIs and click Save.

Now you have all the information you need to implement the authorization code grant type in the PowerBuilder application.

 

Comments (2)
Sunday, Sep 27 2020

I tried this for a Google client (project) with scope "https://www.googleapis.com/auth/gmail.send" and my own client_id and redirect_uri "http://localhost"

"//Step 1: Get the authorization code" uses the PowerBuilder webbrowser control, function navigate() and event resourceredirect(), to obtain the authorization_code. But currently (september 2020) Google OAuth2 no longer supports embedded browsers like the CEF (Cromium Embedded Framework) which the PowerBuilder webbrowser control is based on. In the example I now get the error: "Google Couldn't sign you in. This browser or app may not be secure. Try using a different browser. If you’re already using a supported browser, you can refresh your screen and try again to sign in.". Enabling "Less secure app access" in the Google account doesn't help and also is not recommended by Google.

The inet object doesn't support https and I don't know how the problem can be solved by using the httpclient or oauthclient object (PowerBuilder version 2019 R2 build 2353). Perhaps I overlooked something. If not, does anyone has an idea how to open the Google Consent redirect page in the default system browser and get the response authorization code after the user clicks the Allow button? Or is there a way to still use the webbrowser control?

Similar problem described here: https://stackoverflow.com/questions/62506808/how-do-i-sign-in-to-google-with-cefsharp-browser-in-wpf
See also: https://magpcss.org/ceforum/viewtopic.php?f=10&;t=16764

Comment was last edited 5 years ago by Bas Oversteegen
0
Monday, Sep 28 2020

Hi Bas,

1. I did some further testing based on this article but unfortunately still didn’t reproduce the issue.
2. I suggest that you can change the value of redirect_uri from http://localhost to an address supporting the HTTPS protocol (e.g.: https://www.appeon.com/callback) and see if it works.
Also, please note that at the sixth step “Creating OAuth client ID” of this Creating a YouTube Data API tutorial, you need to set the value of “Authorized redirect URIs” to be consistent with the value of redirect_uri which we are talking about here.

3. We would also suggest that you turn on Google Account sign-in prompts in your Google Account and then try it again.
4. As for the issue of "currently (september 2020) Google OAuth2 no longer supports embedded browsers like the CEF (Cromium Embedded Framework) ", currently, we don’t have a better solution either. You can try to add the code below to the application open event in your PowerBuilder App and see if it works:
WebBrowserSet ("UserAgent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36")

Regards,

0

Find Articles by Tag

BLOB Database Table Schema PowerBuilder Compiler DevOps NativePDF Validation CrypterObject PostgreSQL ODBC driver Event Handler RichTextEdit Control SQL Server Trial Script Visual Studio 64-bit Repository Database Connection Web Service Proxy PDFlib SqlModelMapper WebBrowser .NET Assembly SnapObjects Service WinAPI Oracle CI/CD Authentication SnapDevelop Array Menu Installation SqlExecutor Application Filter External Functions Database Table Data Windows OS Error PowerScript (PS) SOAP Elevate Conference File C# InfoMaker Source Control Class Linux OS .NET Std Framework Stored Procedure SQL Automated Testing Event Handling Import Web API Model RESTClient HTTPClient Testing Debugging Resize PowerServer Web DataWindow JSON Windows 10 Icons OLE Outlook iOS Excel UI Themes REST CoderObject MessageBox Database Object RibbonBar JSONGenerator PostgreSQL ODBC PBVM DragDrop Syntax PFC Window PDF Platform Database Painter .NET DataStore Debug Deployment OrcaScript Variable Migration DataType UI Performance UI Modernization JSON Charts Jenkins Design Azure Text ActiveX Event Authorization Configuration Graph PBDOM Open Source Debugger PowerBuilder (Appeon) API Icon Expression Database Profile XML Database OAuth PowerServer Mobile TFS Export PBNI Branch & Merge PowerBuilder SVN RibbonBar Builder Export JSON TreeView IDE DLL Encryption COM Messagging JSONParser Transaction SDK Mobile Interface Source Code Android Git GhostScript Data License DataWindow OAuth 2.0 Encoding Import JSON TLS/SSL Database Table 32-bit Sort TortoiseGit Bug