Cloud to Cloud OAuth (Rest API)

I’m trying to connect a third party service to my SmartApp connector, going off of the docs here: https://smartthings.developer.samsung.com/develop/guides/cloud2cloud/c2c-oauth.html

So the mobile app is showing all of the correct configuration pages, and opens a webview to my third party login page, but when I successfully authenticate the user and try to redirect the browser to https://api.smartthings.com/oauth/callback (with my access token in the query params), the client is just getting a 401 unauthorized error from SmartThings, and I don’t get any OAUTH_CALLBACK lifecycle.

Is there a particular format that the /oauth/callback endpoint expects the query params to be in? Or is there some sort of authentication header that needs to be attached to the request?

Did you find solution ?
I have a same issues. If you already resolved, please share for us.

You realize that’s the SmarThing developer Beta site, right? Not the official SmartThings developer portal. That doesn’t work with SmartThings yet.

I emailed Samsung developer support directly, they said that they’re still working on Cloud-to-Cloud connectors, and that the OAuth system was being actively developed and might not work yet.

1 Like

Have you seen this C2C device example in SmartThings GitHub? I think it will help you.

In this example I found this urlTemplate for OAuth callback.
urlTemplate: ${lifxOauthEndpoint}/authorize?client_id=${lifxClientId}&state=${installedAppId}&scope=remote_control:all&response_type=code

Also this doc could be helpful for you: https://tools.ietf.org/html/rfc6749
4.1.1. Authorization Request
4.1.2. Authorization Response
state
REQUIRED if the “state” parameter was present in the client
authorization request. The **exact value ** received from the
client.

1 Like

The LIFX c2c example @hyeyoung linked-to is a good example to look at.

I’ll also try and provide some more info here about the OAuth flow here.

Basic steps

  1. Register your OAuth integration with the third-party. The requirements will vary depending on the third-party service. This typically requires registering an OAuth callback URL for the integration. The callback URL should be https://api.smartthings.com/oauth/authorize
  2. Use an OAUTH configuration setting input to prompt the user to authenticate and authorize with the third-party.
  3. Handle the OAUTH_CALLBACK lifecycle event to exchange the authorization code for a token.
  4. Store and use the token to make requests to the third-party.

OAUTH configuration setting

During app configuration, use the OAUTH setting type to allow the user to authenticate with the third-party and authorize the requested permissions. The urlTemplate is the OAuth URI the third-party requires, and will vary by provider.

An example for requesting authorization with GitHub is shown below, requesting authorization for user:email scope. This assumes that the OAuth app has been registered with GitHub, which will provide the Client ID and secret. Note that GitHub will look up the OAuth redirect URI to call with the authorization code based on the client ID (which should be registered as https://api.smartthings.com/oauth/callback), but your third-party may have different requirements, such as specifying the redirect URI as a query parameter to their authorize URL.

settings: [
	{
		id: "githubAuth",
		name: "Authenticate with GitHub",
		description: "Tap to set",
		type: "OAUTH",
		required: true,
		urlTemplate: "https://github.com/login/oauth/authorize?client_id=YOUR-CLIENT-ID&scope=user:email"
	}
]

When users press the input during installation, they will be directed to the third-party (GitHub in the example above), and once authenticated, will typically be asked to grant the specific access permissions being requested by the app. Once the user accepts, that will trigger the OAUTH_CALLBACK lifecycle to your app.

OAUTH CALLBACK lifecycle

Upon successful authentication and authorization, the third-party will call the URI you registered as the callback (again, should be https://api.smartthings.com/oauth/callback) with an authorization code. SmartThings will route this request to your SmartApp with an OAUTH_CALLBACK lifecycle event. Your app should then exchange the authorization code for a token.

The OAUTH_CALLBACK lifecycle includes a oauthCallbackData object on the request, which contains the following information: the ID of the installed app, as well as the query parameters from the OAuth callback (in the urlPath property). This is typically where the auth code can be found. For example, a response from GitHub may look like:

{
	"installedAppId": "234lkjlasd-234u8ufa-ii54u2304",
	"urlPath": "code=0p87asdfj2yn3jldf"
}

The app can then use the returned code to request a token. Continuing the GitHub example, it may look like (example shown in Node.js):

const rp = require("request-promise");
let code = oauthData.urlPath.split("code=")[1];
let opts = {
	url: "https://github.com/login/oauth/access_token",
	method: "POST",
	json: true,
	form: {
		client_id: YOUR-CLIENT-ID,
		client_secret: YOUR-CLIENT-SECRET,
		code: code
	}
};
rp(opts)
	.then(function(tokenResp) {
		let token = tokenResp.access_token;
		// store token associated with this installed app
    })
	.catch(function(err) {
		console.error(`Error getting token from code: ${err}`);
	});

At this point, your app can use the token to make requests to the third-party.

@eric-zeng Did you ever manage to get this working? I am facing the exact same issues - no OAUTH_CALLBACK lifecycle after redirecting the browser to https://api.smartthings.com/oauth/callback (with query params “code” and “state” that were previously received from SmartThings).
If you figured this out, it would be great if you could share your findings.
Thanks!

@yoni_rabinovitch I saw a developer had encountered same issues before. At that time the fix was requesting OAuth callback with exactly same state as I mentioned above.

In LiFX example
urlTemplate: ${lifxOauthEndpoint}/authorize?client_id=${lifxClientId}&state=${installedAppId}&scope=remote_control:all&response_type=code

Also this doc could be helpful for you: https://tools.ietf.org/html/rfc6749
4.1.1. Authorization Request
4.1.2. Authorization Response
state
REQUIRED if the “state” parameter was present in the client authorization request. The exact value received from the client.

The browser is redirected to https://api.smartthings.com/oauth/callback?state=…&code=… but gets a 401 back from SmartThings.

I’m facing the same issue, did you find a solution?

Sorry for not posting earlier, but I did eventually end up getting OAuth to work. I don’t remember exactly what fixed it, but I think my issue was that I had created multiple SmartApps (one in the dev workspace, one using the REST API in the early days of this new system), and I got confused about which I was using, and passed the wrong client id when redirecting the user’s browser to SmartThings.

So I’d just be extra careful that you’re using the correct OAuth client ids and secrets, and set the correct redirect URL.

1 Like

We are having similar issues. We downloaded the nodejs example project that you provide in your docs (example-lifx-nodejs-web-connector). We changed a few stuff to make it work with our cloud but we are having issues.

We are able to get the app in the SmartThings app, inside that, it ask the user to authorize the app to access to our cloud data and when you page does the OAuth redirect to https://api.smartthings.com/oauth/callback with all params (code and state) we are getting 401 error

This is urlTemplate in the settings: https://user.flocloud.co/authorization?client_id=${client_id}&redirect_uri=https%3A%2F%2Fapi.smartthings.com%2Foauth%2Fcallback&response_type=code&state=${installedAppId}

Do we have a way to see logs in your side to see why we are getting 401 error from you? Or why is the lifecycle OAUTH_CALLBACK is never sent?

Hey guys!

I am in stuck with the same issue…

I’ve used callback https://api.smartthings/oauth/callback and after successful login to my service though SmartThings App screen - I see blank screen.
When I open login page with this callback from browser on laptop - I see redirection https://api.smartthings/oauth/callback&code=$CODE&state=$configurationData.installedAppId that completes with HTTP 401.

Has anybody got success when implementing OAuth link to custom backend??

Thanks in advance!!

I have been searching all the docs and forms last three days. But I could not find the exact URL to initiate OAuth flow. Need help with that.

Got this blank screen as well but it seems to work now. ST says they had issues. Now, I have a problem that the ST service is not calling my web-hook endpoint
Edit: Account linking working fine with the Webhook. Just looked in the wrong log :slight_smile: Had to rewrite the service code to move to support schema based device though.

11/24 CLOSED Completed C2C Schema integration with custom OAuth2 service