Skip to content

OAuth SUPLA Broker workflow

Wojciech Frącz edited this page Nov 15, 2018 · 49 revisions

Glossary

Term Definition
clientId Identifier of any OAuth application that is created in SUPLA Cloud.
public OAuth Client Application that was accepted by supla.org administrator and can be authenticated in any registered Target Clouds via Broker Cloud, because it is registered in the Autodiscover.
mapped clientId An identifier of the public OAuth Client in Target Cloud (can be different that the identifier of the same public OAuth Client in the Autodiscover)
Autodiscover A service implemented outside SUPLA Cloud that is responsible for the following.
  1. Maintaining the list and giving a target svrX official server for the given e-mail address; this happens automatically during registration and authentication.
  2. Storing a list of public OAuth Clients. Public OAuth clients are managed by the supla.org administrator.
  3. Registering new Target Clouds and issuing the authorization tokens for them. Registering new Target Cloud can be done in a special form in any Broker Cloud by any user.
  4. Returning a mapped clientId for given clientId and Target Cloud. If the Target Cloud does not have the mapped clientId for the given clientId yet (i.e. during the first authentication attempt to the given public OAuth Client in this Target Cloud), Autodiscover should generate a mapped clientId and secret before returning it. This action can be issued only by a Broker Cloud.
  5. Returning a mapped clientId, secret, redirect URIs, client name and description for given clientId and Target Cloud. The query might come from any Broker Cloud or an authorized Target Cloud (query about itself).
Broker Cloud A SUPLA Cloud instance that knows where the Autodiscover is, and the Autodiscover accepts Broker connections from this. Technically, every SUPLA Cloud instance is capable of acting as a Broker Cloud, but the Autodiscover will accept clientId/secret pair generation requests only from very strict list of SUPLA Clouds. To make it simple, Broker Cloud is any svrX SUPLA Cloud official instance.
Target Cloud A SUPLA Cloud instance that has been registed in the Autodiscover via special form available in Broker Cloud. Broker Cloud will communicate with the Target Cloud when authorization any Public OAuth client according to the workflow presented below. Every Broker Cloud may act as the Target Cloud, too, if the authorizing user has an account on any official svrX SUPLA Cloud instances.

I. Acquiring the authCode with the Broker Cloud

  1. External app tries to authenticate in the Broker Cloud with the following URL: GET https://cloud.supla.org/oauth/v2/auth?client_id=XXX&redirect_uri=http://externalapp.com/auth&response_type=code&scope=account_r
  2. SUPLA Cloud checks if XXX clientId exists in the database.
    1. If it does, it means that we reached the Target Cloud.
      1. If the client has a reference to the public client, Target Cloud queries the AD for public clients list and updates their basic details if needed prior to displaying them in the authorization form (name, descrpition, redirectUris).
      2. Then, the "normal" OAuth process begins. If the user authenticates successfully and grants the application, the authCode is sent back to the redirect_uri provided in the authorization URL. AuthCode contains the Target Cloud address encoded inside. We quit this workflow.
    2. If it does not exist:
      1. If the instance is Target Cloud, it queries the Autodiscover, using the given authorization token, whether it contains such clientId for itself. If might have just been created (step 4.i.a). The Autodiscover responds with the public clientId for the new client to create in Target Cloud. Target cloud then creates a new local OAuth client with a reference to this publicId, BROKER type, and client data fetched from the AD catalog. It sends back the generated mapped client id and secret to AD. AD replaces generated clientId with the mappedId given from the Target Cloud. Now we fall into 2.i.
      2. Else, if the instance is Broker Cloud, it renders a special broker-login form, that contains only username and a checkbox "custom SUPLA Cloud server". If user selects this checkbox, he must provide a custom domain name or IP address that points to his own Target Cloud (we requie SSL here, so only a domain/IP).
      3. If neither of above succedeed, the standard error when invalid clientId is given should be returned to the user and we quit this workflow.
  3. User fills the username and (possibly) the Target Cloud domain/IP and submits. Broker Cloud finds an appropriate address of the Target Cloud (either by autodiscovering the user by username or by using the address to the Target Cloud provided).
  4. The obtained Target Cloud address and clientId requested by the app are used by Broker Cloud to query the Autodiscover to find out if there is a registered Target Cloud with this domain name/IP.
    1. If it does, the Autodiscover returns clientId for the same application in the Target Cloud (without secret!). The clientId is sent to the browser.
      1. If the clientId does not exist in Autodiscover at the moment of query, but the Target Cloud is registered there (i.e. this is the 1st time someone tries to authorize this public OAuth client in this Target Cloud), the clientId is generated now. The Target Cloud will query for this in a moment (2.ii.a). The generation process is transparent to Broker Cloud, i.e. the response is the same regardless of the situation.
    2. If it does not, the Autodiscover returns 404 and an appropriate message is displayed to the user in Broker Cloud. We are back to 2.ii.b.
  5. The browser (in Broker Cloud) receives the Target Cloud's clientId (e.g. YYY). Browser redirects to the Target Cloud with the new clientId and all of the remaining parameters unchanged: GET https://TARGET_CLOUD_ADDRESS/oauth/v2/auth?client_id=YYY&redirect_uri=http://externalapp.com/auth&response_type=code&scope=account_r. With such request, the Target Cloud instance falls into 2.

II. Acquiring the access token with the given authCode

  1. External app tries to use the received authCode (e.g. AAA) to obtain a token. It sends a normal request for this to the Broker Cloud: POST https://cloud.supla.org/oauth/v2/token with the POST data client_id=XXX&client_secret=SS1&redirect_uri=http://externalapp.com/authorize&grant_type=authorization_code&code=AAA
  2. SUPLA Cloud checks if given AuthCode belongs to the current instance by decoding the Target Cloud instance domain name/IP.
    1. If it does, it means that we hit Target Cloud so "normal" AuthCode checking and issuing token takes place. The access token is or is not issued based on the authCode validitiy. Appropriate response is returned. We quit this workflow. The generated token has the Target Cloud address encoded inside.
    2. Else, if the instance is Broker cloud, it queries the Autodiscover, passing clientId (XXX), secret (SS1) and decoded Target Cloud domain name/IP.
    3. Else, or if the authCode is invalid (syntactially), the error is returned. We quit the workflow.
  3. Autodiscover verifies if the public OAuth client's clientId and secret match.
    1. If they do not match, Autodiscover returns a 403 error. This error is passed through to the calling app. We quit the workflow.
    2. Otherwise, Autodiscover returns Target Cloud's mapped clientId and Target Cloud's secret (because we asked for it), e.g. SS2.
  4. Broker Cloud uses the mapped clientId, secret and the authCode to issue a token. It executes a API-API query to the Target Cloud: POST https://TARGET_CLOUD_ADDRESS/oauth/v2/token with the POST data client_id=YYY&client_secret=SS2&redirect_uri=http://externalapp.com/authorize&grant_type=authorization_code&code=AAA
  5. The Target Cloud falls into 2.i. Its response is being forwarded to the calling app.

III. Acquiring the access token with the given refresh token

This is achieved in the same way as II, because the refresh token has the Target Cloud address encoded inside, too.

IV. Registering the Target Cloud in Autodiscover

  1. User goes to https://cloud.supla.org/register-cloud (Broker Cloud). In the form there, enters the e-mail address and cloud domain name, then submits the form.
  2. Broker Cloud verifies if the given e-mail address and domain name are syntactically valid. Then it queries the https://TARGET_CLOUD/api/server-info to find out whether the SUPLA Cloud is working there. If it does, the last check before hitting the Autodiscover is ensuring that the cloudVersion returned by this query is at least 2.3.0, that is, the first version with Broker/Target Cloud workflow implementation. If any of these checks fail, the user receives an error and must provide correct data.
  3. Broker Cloud queries the Autodiscover with given e-mail address and Target Cloud domain name. The Autodiscover verifies if the Cloud is not already registered. If the condition is met, Autodiscover issues a temporary registration token and returns it to the Broker Cloud.
  4. Broker Cloud sends the registration token back to the user, where GUI presents a terminal command that needs to be launched in the Target Cloud in order to finish the registration process. The command contains the registration token issued by the Autodiscover.
  5. User executes the given registration command in Target Cloud host. Target Cloud queries Autodiscover now for an authorization token that will be used for authorization in further communication. The request is authorized by the given registration token. Once the Autodiscover responds with the authorization token, the registration token becomes obsolete and cannot be used again. Target Cloud saves the given token in a safe place and configures itself as a Target Cloud. It authorizes every further request to Autodiscover with the given token.

V. Updating public OAuth Client data in Target Cloud when it is changed in Autodiscover

Redirect URIs, name or description

As described in I.2.i.a., Target Clouds automatically update local mapped clients data before displaying autorization form, using the AD public clients catalog.

Secret or public clientId

If any of these change, we consider all issued refresh tokens and authorizations as expired. Users of this app should reauthorize themselves.

VI. Autodiscover API

I.4 - Get mapped client id

Available only for Broker Clouds.

Query scheme: GET /mapped-client/:publicClientId/:targetCloudUrl
Query example: GET /mapped-client/2_dhSHdnwelknfdsnjEDnjfdsjne/https%3A%2F%2Fsvr3.supla.org
Response scheme: {"mappedClientId": ":mappedClientId"}
Response example: {"mappedClientId": "78_sdDH7sdnhDS&hfds6sd6fds6"}
Possible errors:

  • 403 if requested by a non-broker cloud
  • 404 when client id or target cloud are not known to the AD

I.2.ii.a - query for mapped client publicId

Available only for the Target Clouds.

Query scheme: GET /mapped-client-public-id/:mappedClientId
Query example: GET /mapped-client-public-id/2_dhSHdnwelknfdsnjEDnjfdsjne
Response scheme: {"publicClientId": ":publicClientId"}
Response example: {"publicClientId": "3_asjf27893fjf9"}
Authorization header: Authorization: Bearer kGK8cNGDPCHaJSHRDc7nNG3ndSXefw
Possible errors:

  • 403 if the authorization token does not come from the target cloud given in the query
  • 404 if the authorization is correct, but the client id does not exist or is not mapped to the given Target Cloud

I.2.ii.a - Update mappedClientId and secret from Target Cloud

Available only for the Target Clouds. The request results in replacing current mappedClientId and secret to the clientId and secret given in the request.

Query scheme: POST /mapped-client-credentials/:mappedClientId
Query payload scheme: {"clientId": ":generatedClientId", "secret": ":generatedSecret"}
Query example: POST/mapped-client-credentials/2_dhSHdnwelknfdsnjEDnjfdsjne
Query payload example: {"clientId": "3_Djsfsd7fsadf", "secret": "asdlkfjasldkjfafw3232"}
Response scheme: empty response with HTTP 204 status
Authorization header: Authorization: Bearer 1_kGK8cNGDPCHaJSHRDc7nNG3ndSXefw
Possible errors:

  • 403 if the authorization token does not come from the target cloud given in the query
  • 404 if the authorization is correct, but the client id does not exist or is not mapped to the given Target Cloud

II.2.ii - Get mapped client credentials

Available only for Broker Clouds.

Query scheme: POST /mapped-client/:publicClientId/:targetCloudUrl
Query payload scheme: {"secret": ":publicClientSecret"}
Query example: POST /mapped-client/2_dhSHdnwelknfdsnjEDnjfdsjne/https%3A%2F%2Fsvr3.supla.org
Query payload example: {"secret": "sajdf29jf3982j3"}
Response scheme: {"clientId": ":mappedClientId", "secret": ":mappedClientSecret"}
Response example: {"mappedClientId": "78_sdDH7sdnhDS&hfds6sd6fds6", "secret": "77372hj832jjjdjjJJj"}
Possible errors:

  • 400 if clientId and target cloud are known to the AD but the given secret is not correct
  • 403 if requested by a non-broker cloud
  • 404 if clientId or target cloud are not known to the AD

IV.3. Issue registration token for new Target Cloud

Available only for Broker Clouds.

Query scheme: POST /target-cloud-registration-token
Query payload scheme: {"targetCloud": ":targetCloudUrl", "email": ":email"}
Query example: POST /target-cloud-registration-token
Query payload example: {"targetCloud": "https://my-private-cloud.com", "email": "[email protected]"}
Response scheme: {"token": ":token"}
Response example: {"token": "AALjWwJwgyuLR89esbmb7wr7YprpLy"}
Possible errors:

  • 403 if requested by a non-broker cloud
  • 409 if given target cloud is already registered

IV.5. Register new Target Cloud

Query scheme: POST /register-target-cloud
Query payload scheme: {"targetCloud": ":targetCloudUrl", "registrationToken": ":registrationToken"}
Query example: POST /register-target-cloud
Query payload example: {"targetCloud": "https://my-private-cloud.com", "registrationToken": "AALjWwJwgyuLR89esbmb7wr7YprpLy"}
Response scheme: {"token": ":token"}
Response example: {"token": "1_kGK8cNGDPCHaJSHRDc7nNG3ndSXefw"}
Possible errors:

  • 400 if the given configured targetCloud URL is not the same as was entered in the registration form; it indicates a Target Cloud configuration problem, so user needs to adjust it or generate a new registration token for valid address
  • 403 if the registration token is not valid (does not exist or is expired)

I.2.i.a. Fetching list of public clients

Query scheme: GET /public-clients
If-Modified header: If-Modified-Since: :date where :date is a date in one of the allowed formats of the last cached response in Target Cloud
If-Modified header example: If-Modified-Since: Sat, 20 Oct 2018 08:49:37 GMT
Authorization header: Authorization: Bearer kGK8cNGDPCHaJSHRDc7nNG3ndSXefw
Response scheme: [{"publicId": ":publicId", "name": ":name", "description": ":description", "longDescription": ":longDescription", "websiteUrl": ":websiteUrl", "redirectUris": [:redirectUris], "defaultScope": ":defaultScope", "defaultRedirectUri": ":defaultRedirectUri"}, ...]
Response example: [{"publicId": "4_ABC", "name": "Some App", "description": {"EN": "This is some app."}, "longDescription": {"EN": "This is long description. May even use a <b>HTML!</b>."}, "websiteUrl": "https://some-app.com", "redirectUris": ["https://some-app.com/auth"], "defaultScope": "account_r channels_ea", "defaultRedirectUri": "https://some-app.com/auth"}]
Internationalization: The description and longDescription can be sent as a string (as shown above) or an object, where keys refer to the locales supported by the SUPLA Cloud. Example: "descripition": {"pl": "Polski opis", "en": "English description"}
Possible errors:

  • 304 if the client's list was not modified since the date given in the header
  • 403 if the authorization token is not valid