HTTP_AUTHORIZATION Bearer header missing, but is included in json?

I have created a Cloud Connector SmartThings Schema webhook and set up oauth so that a Django app on my cloud is receiving http POST requests from SmartThings. This is all working fine and my oauth provider is getting an access token, but when a call such as discoveryRequest is made to my api, there is no HTTP_AUTHORIZATION header in the request, even though it is in the json body. This is not entirely the end of the world as I can manually get the token from the json body and lookup the associated user in the database, but the oauth module (django-oauth-toolkit) actually expects this as a header.
I am not sure why this isn’t being sent, I have made similar webhooks for Alexa and Google Home and they do send the header. Perhaps I’m using the wrong oauth type?

1 Like

Pretty sure you can get some help from @nayelyz !

2 Likes

Welcome to the SmartThings Community, @willemmerson!
I verified this behavior with our engineering team, they mention the authentication info is only sent in the Request’s body so, you’re on the right track extracting it from there.
Eg.

body: {
    headers: {
      schema: 'st-schema',
      version: '1.0',
      interactionType: 'discoveryRequest',
      requestId: 'e99b644a-4900-...'
    },
    authentication: { tokenType: 'Bearer', token: 'xxxx' } /*Token provided by your Oauth server*/
}

Remember to mark the solution of this post. In case you have more questions, feel free to post them here and we can dig in further.

I can get the token from the request body and this works, thanks.
However, I am confused. According to the official oauth2 spec (rfc6750), clients should send the token in the authorization header:

Clients SHOULD make authenticated requests with a bearer token using
the "Authorization" request header field with the "Bearer" HTTP
authorization scheme.  Resource servers MUST support this method.

In this case SmartThings is the client and our servers are the Resource servers, so if it’s not sending the headers then the SmartThings server isn’t oauth2 compliant.

What I’m confused about is that no-one else seems to have noticed this, I can’t be the first person to use this api, yet anyone else who tries to use this api with a standard oauth2 library should run into the same problem. But there are no other issues on the forums, which makes me think I am misunderstanding the whole thing! :thinking:

1 Like

Exactly. I’ve just had the same issue. The token should be in the header. My gateway handles all the OAuth2 authentication mechanisms, and it doesn’t let through the SmartThings’ requests because they aren’t properly authenticated.

I guess that this also affects the refresh token flow, as I guess by looking at the documentation that expired tokens must be notified responding with a globalError object of TOKEN-EXPIRED.

What I wonder is if on recieving the TOKEN-EXPIRED response, the SmartThings backend will implement the refresh token OAuth2 flow correctly…

Hi @grequena,
Regarding your query please consider that:

  • The OAuth 2.0 Authorization Framework is meant to allow the exchange of accessTokens between two parties.
  • For the OAuth flow, the ST Schema provides the tokens in both, the header and the body of the request. This flow is executed when the user logins to your Cloud and you get a Reciprocal Access Token from ST (this is before the discovery interaction)
  • The Schema interactions, Discovery, StateRefresh, etc. are not part of the OAuth flow, but the ST Schema implementation itself, here is where it provides the Access Token in the body of the requests.
  • The OAuth 2.0 Authorization framework doesn’t regulate how the Access Tokens are handled internally after they were granted, therefore ST-Schema is complying with the OAuth framework specification

Considering the information above, you can get the Access Token from the request body of the ST Schema interactions: Discovery, StateRefresh, Command, and, State and Discovery callbacks.

1 Like