Written by

Question Leon Stokes · May 13, 2019

From Cache how to Retrieve and Use/Reuse a Bearer Token to authenticate and send data to REST web service?

Need a sample of  using %Net.HttpRequest and %NetHttpResponse  from Cache to retrieve and then use/reuse a bearer token to send json data to a REST web service.

Comments

Pravin Barton · May 13, 2019

For the first part of your question, here's a sample method that gets a bearer token from the request:

ClassMethod GetAccessTokenFromRequest(pRequest As %CSP.Request = {%request}) As %String
{
	Set accessToken=""
	Set authorizationHeader=pRequest.GetCgiEnv("HTTP_AUTHORIZATION")
	If $zcvt($piece(authorizationHeader," ",1),"U")="BEARER" {
		If $length(authorizationHeader," ")=2 {
			Set accessToken=$piece(authorizationHeader," ",2)
		}
	}
	return accessToken
}

EDIT: And here is a full sample of a REST handler that retrieves a bearer token and reuses it to make a request against another REST service.

Class API.DemoBearerToken Extends %CSP.REST
{

Parameter APIHOST = "localhost";

Parameter APIPORT = 52773;

Parameter APIPATH = "/some/other/path";

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/example" Method="GET" Call="example"/>
</Routes>
}

ClassMethod example()
{
	set accessToken = ..GetAccessTokenFromRequest(%request)
	set req = ##class(%Net.HttpRequest).%New()
	set req.Https = 1
	set req.SSLConfiguration = "some ssl config"
	set req.Server = ..#APIHOST
	set req.Port = ..#APIPORT
	set req.Authorization = "Bearer "_accessToken
	$$$ThrowOnError(req.Get(..#APIPATH))
	set %response.Status = req.HttpResponse.StatusCode
	set %response.ContentType = req.HttpResponse.ContentType
	if req.HttpResponse.StatusCode <= 400 { //if not an error response
		set jsonData = {}.%FromJSON(req.HttpResponse.Data)
		write jsonData.%ToJSON()
	}
	return $$$OK
}

ClassMethod GetAccessTokenFromRequest(pRequest As %CSP.Request = {%request}) As %String
{
	Set accessToken=""
	Set authorizationHeader=pRequest.GetCgiEnv("HTTP_AUTHORIZATION")
	If $zcvt($piece(authorizationHeader," ",1),"U")="BEARER" {
		If $length(authorizationHeader," ")=2 {
			Set accessToken=$piece(authorizationHeader," ",2)
		}
	}
	return accessToken
}

}

0
Leon Stokes  May 13, 2019 to Pravin Barton

Thanks for your response. Will this work if the REST web service I am targeting is a 3rd party not running Cache or using CSP?

0
Leon Stokes  May 15, 2019 to Leon Stokes

I have Cache 2016.1 (not Ensemble or IRIS) and need to duplicate the functionality of this C# .net code. The target REST web service is a 3rd party not using Intersystems products.

public static TokenResponseModel getBearerToken(string siteUrl, string Username, string Password)
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(siteUrl);
            client.DefaultRequestHeaders.Accept.Clear();

            // uncomment to allow self signed certificates for https requests
            System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

            HttpContent requestContent = new StringContent("grant_type=password&username=" + Username + "&password=" + Password, Encoding.UTF8, "application/x-www-form-urlencoded");

            HttpResponseMessage responseMessage = client.PostAsync("Token", requestContent).Result;

            if (responseMessage.IsSuccessStatusCode)
            {
                string jsonMessage;
                using (Stream responseStream = responseMessage.Content.ReadAsStreamAsync().Result)
                {
                    jsonMessage = new StreamReader(responseStream).ReadToEnd();
                }

                TokenResponseModel tokenResponse = (TokenResponseModel)JsonConvert.DeserializeObject(jsonMessage, typeof(TokenResponseModel));

                return tokenResponse;
            }
            else
            {
                return null;
            }
        }

0
Stephen Wilson  May 17, 2019 to Eduard Lebedyuk

Great article!

Can you enable HTTP Bearer token authentication on Web Applications via the System Management Portal?

All I see under 'Allowed Authentication Methods' are options for:

  • Unauthenticated
  • Password 
  • Login Cookie

Perhaps I am missing a trick somewhere?

0
Eduard Lebedyuk  May 17, 2019 to Stephen Wilson

Do you want to auth using Bearer aginst external REST API?

If so, you don't need web app config, just the code by @Pravin Barton 

0
Stephen Wilson  May 20, 2019 to Eduard Lebedyuk

I was hoping to convert the above sample into an Internal REST API so that Bearer Authentication could replace Basic Authentication

0
Eduard Lebedyuk  May 20, 2019 to Stephen Wilson

First create a REST API. After that override AccessCheck method in your REST broker to check for bearer token.

0
Eduard Lebedyuk  May 15, 2019 to Leon Stokes

yes, the proposed solution would work with any external REST API.

0