Accessing Google APIs from InterSystems IRIS, using OAuth2
Tags: intersystems, iris, oauth2, api
Published: 2021-06-29 06:55:03

Suppose you need to call a feature, that would help your InterSystems IRIS server application to provide some cool functionality for your customers. You know there are many libraries available on the internet, so you do some googling and find a decent one at Google Cloud Platform and its API Library.

To use such API library, you need to solve just “a little” issue – properly authorize yourself / your application to Google.

This can be done using more and more common standard of today’s connected applications – the OAuth2 framework.
I am not going to dive into any details of OAuth2 specification, as there are many very nice articles and tutorials available. Rather, I am going demonstrate how to authorize InterSystems IRIS client (in this case a CSP application) with Google.
In this article, I will utilize some code and settings that I published earlier, in 2016 at InterSystems Developer Community. (See [https://community.intersystems.com/post/intersystems-iris-open-authorization-framework-oauth-20-implementation-part-1](https://community.intersystems.com/post/intersystems-iris-open-authorization-framework-oauth-20-implementation-part-1) for original article.) 
But as time has progressed since then and we have published new versions of InterSystems IRIS, I take this as a good opportunity to refresh the original demo project.

Let’s start with pre-requisites – Google application.
I am using the same demo that was demonstrated in the original post (see above). Luckily, there were no major changes to OAuth2 implementation by Google so we can use existing project – GS2016 OAuth2 Demo. In your case, it is your responsibility to register your client application at Google Cloud Platform, so your configuration would be different.
A good starting point is [here] (https://developers.google.com/identity/protocols/oauth2).
Here, we fit **Web server application** case.

A Cache Server Page has been created, where all necessary code is shown in order to check whether page has valid access token so it can invoke Google APIs of interest. If there is no access token available, then page will: 
•	Obtain OAuth2 credentials from InterSystems IRIS OAuth2 registry entries.
•	Obtain access token from Google Authorization Server.
•	Examines scopes of access granted by the user.
•	Invokes some Google APIs with access token.

You also need to have a Web Server configured to host your Cache Server Pages applications and support HTTPS protocol.


A source code of the Cache Server Page (Web.OAUTH2.Google.cls) can be found at [github](https://github.com/dkutac/iris-oauth2-google-demo).
Let’s have a look at important code parts of the client.
```objectscript
Class Web.OAUTH2.Google Extends %CSP.Page

/// This refers to name of client registered with Google Authorization Server
Parameter APP = "Google";

classmethod OnPage() as %Status
	
#define LOCALHOST $System.INetInfo.LocalHostName()

// we define list of scopes, these define API we want to call				
set scope="openid https://www.googleapis.com/auth/userinfo.email "_
 "https://www.googleapis.com/auth/userinfo.profile "_
 "https://www.googleapis.com/auth/drive.metadata.readonly "_
 "https://www.googleapis.com/auth/calendar.readonly"

// 1. Check if we have an access token from oauth2 server stored locally with registered client application (client id, client secret, ...)
set isAuthorized=##class(%SYS.OAuth2.AccessToken).IsAuthorized(..#APP,,scope,.accessToken,.idtoken,.responseProperties,.error)		

// Google has no introspection endpoint - nothing to call - the introspection endpoint and display result -- see RFC 7662.  
// our API to retrieve user information from access token		
$$$THROWONERROR(sc,##class(%SYS.OAuth2.AccessToken).GetUserinfo(..#APP,accessToken,,.jsonObject))

// here we perform actual calls to APIs (a separate class method in the CSP page, see below)
do ..RetrieveAPIInfo("/drive/v3/files")
do ..RetrieveAPIInfo("/calendar/v3/users/me/calendarList")			

// here we construct redirect page (we redirect back to the same page)
// in this case, there is a virtual application called “app” defined at InterSystems Webserver Gateway 
set redirect="https://"_$$$LOCALHOST_"/app/csp/demos2/Web.OAUTH2.Google.cls"
	
// these parameters are telling Google how to proceed with authorization					
set properties("approval_prompt")="force"
set properties("include_granted_scopes")="true"
  				
// 2. Obtain Access token from Google Authorization Server for our registered client
set url=##class(%SYS.OAuth2.Authorization).GetAuthorizationCodeEndpoint(..#APP,scope,redirect,.properties,.isAuthorized,.sc)

//ClassMethod RetrieveAPIInfo(api As %String)
#define OAUTH2ROOT	"https://www.googleapis.com"
// construct HTTP request, add access token and call given api
set tHttpRequest=##class(%Net.HttpRequest).%New()
$$$THROWONERROR(sc,##class(%SYS.OAuth2.AccessToken).AddAccessToken(tHttpRequest,"query","GOOGLE",..#APP))
$$$THROWONERROR(sc,tHttpRequest.Get($$$OAUTH2ROOT_api))
set tHttpResponse=tHttpRequest.HttpResponse
// now feel free to parse received tHttpResponse object
```
#InterSystems IRIS OAuth2 client registry entries.
Access tokens, refresh tokens and other OAuth2 related information is stored in InterSystems IRIS system database. For client applications, two sets of entries are kept. 
•	List of OAuth2 servers.
•	List of clients defined for each OAuth2 server.
Following picture shows how definition of Google Authorization Server within InterSystems IRIS Data Platform

![OAuth2 client - server description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q8409w8op3tiz06c6d21.png)

Next picture shows some of details for “Google” client (not visible here, the name is in General tab)
![OAuth2 client - client configuration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6nk30v569do1731vio4.png)
 
Client ID and Secret need to be copied from the Google Cloud Platform, APIs and Services, Credentials page.
How to run:
Navigate your browser to your CSP Page (in my case http://localhost/app/csp/demos2/Web.OAUTH2.Google.cls )
You shall see page like this:
![CSP Client without access token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9vzxl79te0l2dacsb6x1.png)
As you start a new session, there is no access token available and stored with InterSystems IRIS instance. Click the hyperlink. You will be prompted by Google to provide your user identity (account, password) and allow access to resources given by scope parameter.
Once you successfully obtain access token, your page will change:

![CSP Client with access token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdydspenzym151h4e6vd.png)
Now, to call Google APIs, click the hyperlink again and you will receive information from Google. Results may vary, depending on how you configure your Google Cloud Platform instance.

![CSP Client sample output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c7y6pr032qjy1f0hb6f8.png)
I don’t have some APIs enabled, but that’s irrelevant; we just demonstrated how to configure our application to authorize with Google OAuth2 Server.

Conclusion:
Like other frameworks, InterSystems IRIS provides set of libraries that allow handling various flows of OAuth2 authorization. The Cache Server Page discussed in this article demonstrates how easy it is to authorize application written with InterSystems IRIS Data Platform against external OAuth2 server and use obtained access token to call external APIs and retrieve data they provide.