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.

  • + 1
  • 1
  • 130
  • 7
  • 1

Answers

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
}

}

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?

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;
            }
        }

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

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?

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

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