/sc_assets/75/logo.png

Select a topic:

Choose from one of the topics below to browse other articles

Articles & Information.

Authentication

Last updated by Jens N. on March 27, 2015 10:31

Authentication and authorization in SalesKing is done using the OAuth 2.0 protocol. OAuth supports different flows depending on the type of client application(website, desktop, mobile app). As a starting point we support the Server-side flow(authorisation code flow), meaning you are using a website and a server-side client(ruby,php, ..) to talk to SalesKing.

User Login

Access to SalesKing is always in a company-scope, identified by the current subdomain. A user working in multiple companies must allow an app for each account.

A login involves three steps:

  • User authentication: The user MUST login to SalesKing before he can authorize any app, so we know it's really him.
  • App authorization:  Apps SHOULD define permissions(in scope - param) as capabilities users provide to an app. No Scope == All Permissions
  • App authentication: An app MUST identify itself with their credentials(app id+secret), ensuring the user is giving their information to your app and not someone else.

Upon completion, your app is issued an user access token that enables you to access the user's information(within a company) and take actions on their behalf.

Authorisation & Permissions

Your app SHOULD define only needed permissions using the scope-parameter in authorization requests. Permissions are space delimited, each consisting of a context-name, optionally followed by(colon) a csv list of permission names. Permissions to view companies/current and users/current are always added. Also read Permissions in detail.

If you choose to add all permissions which the allowing user has, skip the scope param:

No Scope == All Permissions of the current user. 

For testing and internal apps this might be ok, BUT if somebody gets hold of the access he can do BAD THINGS!!

scope=api/contacts api/invoices:create,read,update,delete
api/contacts = All permissions CRUD
api/invoices:read = Only read for invoices

All available permissions can be found at /api/auth_permissions, and can also be filtered: /api/auth_permissions?q=api

Server-side Flow

User authentication and app authorization are handled within our oAuth Dialog, shown on authorization requests(GET /oauth/authorize). To see this dialog the user has to login, proving its really him. The app, identified by its client_id( gen. on app creation), is authorized by the user with the given permissions(scope-param). On approval the users browser is redirected back to the given redirect-url(redirect_uri param). The redirect_uri must be within the same domain as the Site URL you specified when creating the app.

1. GET the oAuth dialog:

https://SUBDOMAIN.salesking.eu/oauth/authorize?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=api/contacts:read

and after login, a user sees something like this:

If the user clicks the "Don't Allow"-Link he gets redirected to your app's redirect_uri with the error parameter:

http://YOUR_URL?error=user_denied

2. Redirected back to your App

If the user allows your app, his browser is redirected (302) to the URL in redirect_uri with an authorization code:

http://YOUR_URL?code=SOME_LENGTHY_CODE

3. Get Access Token

The last step: app authentication, can only be done using this code. To gain permanent access your app is issued an access token which is required for all API calls.

Our token endpoint expects the following params:

https://SUB.salesking.eu/oauth/token?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE

If your app is successfully authenticated, the access token, it's expiry time in seconds and the a state parameter(if used) are returned in a JSON object. You can also request an offline token, which does not expire, by adding "offline_access" to the scope param. Please be careful with such as it is a security risk.

{
"access_token":"fc4f10073d31c6cba68922f0356c6b8e",
"state":"Random string you should add when requesting oAuth dialog. Security-check if its still the same.",
"expires_in":3599
}

Once the token expires(default: 1 h), you will need to re-run the steps above to generate a new code and access_token. The oAuth dialog is NOT shown again if the user has already authorized your app.

4. Use Access Token

The access token is used in every request, and can be passed as an url parameter or inside the request header:

# as url param
my.salesking.eu/api/contacts?access_token=THE_ACCESS_TOKEN<br>#as auth header
Authorization: Bearer THE_ACCESS_TOKEN<br>

Implicit Grant (js-apps)

Javascript client apps, running in a browser, are not able to keep an app-secret in a save place. They should therefore use the Implizit Grant, which directly returns the access token. The redirect_uri must be within the same domain as the Site URL you specified when creating the app!

1. GET the oAuth dialog:

Set params[response_type]=token activates and returns the token in the callback uri.

https://SUBDOMAIN.salesking.eu/oauth/authorize?client_id=YOUR_APP_ID&response_type=token&redirect_uri=https://YourApp.com/activate_callback&scope=api/contacts:read

Your app will receive the token as url param: https://YourApp.com/activate_callback?access_token...

Browser JS apps cannot run within a SalesKing canvas page. Such apps receive encrypted params, which need the client secret to decrypt them.

Errors

If app authentication fails, an HTTP 400 is issued and an array of errors is returned as JSON:

[
{"error":"invalid_client", "error_description": "App for token could not be found" },
{"error":"invalid_client", "error_description":"Client id or secret invalid"},
{"error": "invalid_grant", "error_description":"Invalid code, only use it once."},
{"error": "invalid_grant" , "error_description": "redirect_uri is not included in app url"},
{"error": "invalid_grant" , "error_description":"The given state does not match the state when the token was requested"}
]

Example

A minimalistic PHP example to demonstrate the server-side flow:

PHP Authorisation Example