-
Notifications
You must be signed in to change notification settings - Fork 45
OAuth SUPLA Broker workflow
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.
|
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. |
- 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
- SUPLA Cloud checks if
XXX
clientId exists in the database.- If it does, it means that we reached the Target Cloud.
- 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).
- Then, the "normal" OAuth process begins. If the user authenticates successfully and grants the application, the
authCode
is sent back to theredirect_uri
provided in the authorization URL. AuthCode contains the Target Cloud address encoded inside. We quit this workflow.
- If it does not exist:
- 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. - 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).
- If neither of above succedeed, the standard error when invalid clientId is given should be returned to the user and we quit this workflow.
- 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,
- If it does, it means that we reached the Target Cloud.
- 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).
- 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.
- If it does, the Autodiscover returns clientId for the same application in the Target Cloud (without secret!). The clientId is sent to the browser.
- 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.
- 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.
- If it does, the Autodiscover returns clientId for the same application in the Target Cloud (without secret!). The clientId is sent to the browser.
- 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.
- 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 dataclient_id=XXX&client_secret=SS1&redirect_uri=http://externalapp.com/authorize&grant_type=authorization_code&code=AAA
- SUPLA Cloud checks if given AuthCode belongs to the current instance by decoding the Target Cloud instance domain name/IP.
- 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.
- Else, if the instance is Broker cloud, it queries the Autodiscover, passing clientId (
XXX
), secret (SS1
) and decoded Target Cloud domain name/IP. - Else, or if the authCode is invalid (syntactially), the error is returned. We quit the workflow.
- Autodiscover verifies if the public OAuth client's clientId and secret match.
- If they do not match, Autodiscover returns a 403 error. This error is passed through to the calling app. We quit the workflow.
- Otherwise, Autodiscover returns Target Cloud's mapped clientId and Target Cloud's secret (because we asked for it), e.g.
SS2
.
- 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 dataclient_id=YYY&client_secret=SS2&redirect_uri=http://externalapp.com/authorize&grant_type=authorization_code&code=AAA
- The Target Cloud falls into 2.i. Its response is being forwarded to the calling app.
This is achieved in the same way as II, because the refresh token has the Target Cloud address encoded inside, too.
- 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. - 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 thecloudVersion
returned by this query is at least2.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. - 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.
- 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.
- 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.
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.
If any of these change, we consider all issued refresh tokens and authorizations as expired. Users of this app should reauthorize themselves.
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
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
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
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 givensecret
is not correct -
403
if requested by a non-broker cloud -
404
if clientId or target cloud are not known to the AD
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
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 configuredtargetCloud
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)
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