OnInit() Question - Ens.BusinessOperation (HTTP.OutboundAdapter)
I have a question about using OnInit() within a Ens.BusinessOperation.
When you include OnInit(), does OnInit() only execute when you start a Business Operation? Or does it execute OnInit () every time you send a REST request to the operation. I am trying to pinpoint when the best time is to execute the POST command to get the Token
I am needing to get a Bearer Token from a REST POST call and return the Authorization key prior to making the rest of the REST calls to pull down data.
When not using OAuth, what have you done to get the Token prior to executing any Requests?
Thanks
Scott
Hello @Scott Roth
The OnInit Method executed once start/restart a Business Operation. Maybe You can create additional HTTP Business operation and call this operation based on the create/renewal for OAuth token. Eventually you can call that operation as sendrequestsync and get the token in your actual business operation. Please share if any additional thoughts about this flow.
Thanks!
OnInit() only gets called when starting the operation.
If your tokens have an expiration time then you need to check if the token is expired on each call and fetch a new one if needed. You can just store the token and expiration time in properties and check them on each call.
This is all relatively new to me, so please bear with me. Since I am getting a Token it's not the same as OAuth, correct? Nothing in the Vendors documentation says that it is OAuth, it just says..."Authentication method is a token-based approach".
So, if that is the case, I can't use the %SYS.OAuth2.AccessToken methods to verify IsAuthorized, and GetAccessTokenClient correct?
There could be non-OAuth token-based authentication methods. I expect the %SYS.OAuth stuff won't work for something non-OAuth.
What does the payload look like that you have to send in order to get a token? We can see if it looks like OAuth or not.
The Payload needs to have the username which is an email, and the password.
POST /v2/login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
email=test%40test.com&password=test123
It doesn't look like OAuth. If it were, the payload should include a grant_type and username is called "username" rather than "email":
https://www.oauth.com/oauth2-servers/access-tokens/password-grant/
https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/
Thats what I thought, so since it is not how do I verify the token is expired? or should I just get a new token every time?
Good question. In OAuth the response will include the expiration time, so that's what I was expecting here.
If the response doesn't include an expiration time does the vendor's documentation say anything about if tokens can be used for more than 1 request and if so how long it's valid for? If you know it's supposed to be valid for 60 minutes then you could just log the time when you requested the token and use that to track it.
From my testing in Postman, the JWT that is sent back has an "expires_in" included in the response.
{"access_token":"...........","token_type":"bearer","expires_in":"3600"}
What we have typically built into our code is that the OnInit() will just call a separate ..GetAuthorizationToken method where the authorization code is stored.
Then in our GET methods (or whatever API endpoint you are consuming), if we receive a '401 Unauthorized' HTTP Status Response, at that point we will call out to the ..GetAuthorizationToken method. We will get a fresh token, and then continue down the GET method.
There is no need to get a fresh token every time. If we are getting 200 OK responses back, the token must be valid. It should be that when you get a 401 status response, you can capture that into an "if" statement and just call out to your GetAuthorizationToken method at that point.
Can you call GetAuthorizationToken even though you aren't using OAuth?
Yes, we built GetAuthorizationToken method ourselves so you can compose the request however you need.
Basically, in order to get your token, you are just making another REST request to their authorization endpoint.
Example:
Method GetAuthorizationToken() As %Status { //Authenticate with System set tHttpResponse=##class(%Net.HttpResponse).%New() set tHttpRequest = ##class(%Net.HttpRequest).%New() set tHttpRequest.ContentType="application/x-www-form-urlencoded" //Get username and pwd out of Credential store set objCred = ##class(Ens.Config.Credentials).%OpenId(..Adapter.Credentials) //Insert the username and pwd (in your case may be "email" instead of "username") do tHttpRequest.InsertFormData("username",objCred.Username) do tHttpRequest.InsertFormData("password",objCred.Password) //add any other things the request may need //send auth request set tURL=..AuthURL set tSC = ..Adapter.SendFormDataArray(.tHttpResponse,"POST",tHttpRequest,"","",tURL) //Get response, were our credentials accepted? set tStatusCode = tHttpResponse.StatusCode $$$TRACE("Authorization Status Code [" _ tStatusCode _ "]") if tStatusCode = 200 { set ..tToken=tHttpResponse.access_token Return $$$OK } else { Quit $$$ERROR("5001", "tStatusCode - can't auth with System") } } }
💡 This question is considered a Key Question. More details here.