Authentication and Skuid¶
Skuid provides several different mechanisms for authenticating to external services. You can choose to store (shared and/or individual) credentials securely within Salesforce, or you can choose to leverage standards like OAuth to delegate authentication to a third party.
Data Source Authentication Methods¶
These authentication methods are available at the data source level.
No Authentication¶
Select this option if your service is publicly available and does not need any type of credentials for access. This method could also be relevant for services that are behind a firewall and the data source has Use Apex Proxy unchecked.
Basic HTTP Authentication¶
While OAuth is the recommended authentication flow for most data sources, Skuid also allows for basic HTTP authentication—in short, sending encrypted user credentials to a data source to login.
Skuid encrypts all usernames and passwords using AES-256 symmetric encryption. Credential records are stored in Protected Custom Settings which are inaccessible to querying through any API—only Skuid internal code can access this information, and Skuid does so only when making authentication requests to data sources. Your company’s Salesforce administrator can change the encryption key from the Skuid Settings page.
Note
It is impossible for Skuid administrators to login as a different end user and gain access to that user’s data source credentials.
With Basic HTTP Authentication, credentials are sent Base64 encoded as a header with every request. If you select this authentication method, Skuid will automatically construct the Authorization
as shown below. For example, if a username of Aladdin
and a password of open sesame
were provided, Skuid would construct the following header.
1 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
When configuring basic HTTP authentication for a data source, you must specify a credential source. This can either be:
- Shared by all Site Users (Skuid Platform) / Shared Org-wide (Skuid SFX): If you want all end users to share the same username and password to access the external data system, select this option and enter the credentials on the form that appears below the picklist.
- Shared Per-Profile, with optional Org-wide Defaults: If you want end users to share a login based on a Salesforce profile, enter the credentials on the form that appears below the picklist. You may also enter default org-wide credentials.
Note
This credential source is not currently available on Skuid Platform.
Per-User, with optional shared Site-wide Defaults (Skuid Platform) / Per-User, with optional Profile / Org-wide Defaults (Skuid SFX): Allows users to enter their own individual credentials for a data source, with optional default credentials available if needed.
End users manually add their own credentials within the Skuid UI:
- In Skuid Platform, credential management is done in My Settings > Username / Password Credentials.
- In Skuid SFX, credential management is done in My Credentials.
Separate Authentication URL¶
With the Separate Authentication URL option, Skuid will first make a request to a separate authentication URL, retrieve a token, and then use that token on subsequent requests to the service.
When configuring a Separate Authentication, you can (but are not required to) specify a credential source. This can either be Shared: Org-Wide, Shared: Per-Profile, or Per-User.
- If the Shared: Org-Wide setting is selected, then you will be prompted to enter the shared username and password.
- If the Per-Profile, or Per-User settings are selected, then the credentials need to be entered on a separate screen.
Authentication Provider (OAuth, Custom, etc.)¶
Authentication Providers in Skuid allow for the use of specialized protocols (like OAuth) or custom Apex Code to handle Authentication. Using Authentication Providers, Admins can configure OAuth connections or Custom Apex code.
Authentication Provider Authentication Methods¶
The following methods require the use of data source in conjunction with an authentication provider.
Custom Apex Authentication¶
This option is currently only used internally to support the Sharepoint data source type’s custom authentication process.
OAuth 2.0 / Open ID¶
OAuth is an open source standard for authentication. It allows a third party (Skuid) to create models on services where Skuid never actually receives or knows the username or password required to access that service. The OAuth spec describes several different grant types (or flows) that can be used to gain access to a resource server (External Web Service).
Warning
Skuid does not currently support authenticating with OAuth 1.
Additional resources¶
- Salesforce documentation: Digging Deeper into OAuth 2.0 in Salesforce
- OAuth 2.0 Authorization Framework Spec from the IETF
OAuth Grant Type Authentication Flows¶
When configuring authentication providers, there are several grant types to choose from. Depending on your choice, end users will go through a different authentication flow when they attempt to use a data source.
Authorization Code Grant [[]]¶
In the Authorization Code OAuth flow, Skuid uses a popup to redirect the end user to an authorization endpoint, where it provides a Client ID to identify the client requesting access on behalf of the user. The end user then enters credentials.
Because this is in a separate popup window, Skuid has no access to the credentials being entered. This interaction is completely between the user and the Authorization Server. Once the end user enters credentials here—and it is determined by the authorization server that the credentials are correct—Skuid receives an authorization code via a callback URL, also known as a redirect URI. Once Skuid has an authorization code, it can exchange that code for an access token from an access token endpoint. Until the token expires (or is otherwise invalidated), it can be used to gain access to the resource server.
The access token has a limited lifespan, specified by expires
and expires_in
parameters sent to the client in the access token response. Once the access token expires, a new access token must be requested. One of the benefits of the Authorization Code grant, as opposed to the Implicit grant, is that it provides a mechanism for new access tokens to be automatically requested on the end user’s behalf when access tokens expire. It does this by means of refresh tokens.
Typically, the first time an end user successfully retrieves an access token via an Authorization Code flow, the authorization server sends back a refresh token in addition to an access token. Refresh tokens functionally let an end user bypass the authorization code step and skip right to the access token request. (This is significant because it requires manual user interaction with the screen to re-authorize.) If Skuid has a refresh token stored for a particular service, it can use this to perform a refresh token grant flow to request new access tokens for the user—and do it behind the scenes, as needed, when access tokens expire. This makes the combination of the Authorization Code / Refresh Token Grants a better user experience than the Implicit Grant, which does not support refresh tokens.
Key Takeaways:
- Keeps user credentials secret
- Allows new access tokens to be automatically obtained via refresh tokens
What happens in this grant flow [[]]¶
Step 1: Open a popup window at a particular URL
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Step 2: If authorization is successful, the popup window is redirected to a callback URL/redirect URI.
HTTP/1.1 302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
Step 3: Using the Authorization Code received in Step 2 to request an access token
Both the Client Id and Client Secret are typically used to authenticate the client in this step.
POST /token HTTP/1.1
1 2 3 4 | Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
|
Step 4: An access token is returned
HTTP/1.1 200 OK
1 2 3 4 5 6 7 8 9 10 | Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
|
Step 5: Using the access token, make the actual request to the resource server
Client Credentials [[]]¶
This grant type uses the client ID and client secret REST API credentials for authentication, instead of individually authenticating specific end users through an authorization code or username/password credentials.
Implicit Grant [[]]¶
In the implicit grant, the client is issued a token directly. Since this flow is initiated from the client (i.e., the end user’s web browser), it does not authenticate the client using a client secret. Only the public client Id is used.
Key Takeaways
- Keeps user credentials secret
- Does not allow refresh tokens; end users must reauthorize when access tokens expire
What happens in this grant flow [[]]¶
Step 1: Client makes a request to the authorization server
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Step 2: If authorization is successful, the client is redirected and given an access token
HTTP/1.1 302 Found
1 | Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA
|
Resource Owner Password Credentials Grant [[]]¶
In this grant flow, the resource trusts the client enough to give away its credentials.
Key Takeaways
- Stores credentials in Salesforce
- End users do not have to enter credentials often
What happens in this grant flow [[]]¶
Step 1: Request an access token using the username and password
POST /token HTTP/1.1
1 2 3 | Host: server.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
|
Step 2: If authorization is successful, the client is given an access token
HTTP/1.1 200 OK
1 2 3 4 5 6 7 8 9 10 | Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
|
Troubleshooting Tips for Authentication¶
To troubleshoot OAuth issues, you can use Skuid’s Javascript OAuth API to examine the OAuth response for a particular service for which authentication was requested. For instance, if you were having issues connecting to Dropbox, you could inspect the OAuth response by going into the JavaScript console and entering:
1 | skuid.oauth('dropbox').getAuthResponse();
|
This returns an object which should contain details of any errors that occurred with your OAuth flow for that service.
- For all standard OAuth provider types, this will be accessible via
skuid.oauth(provider_type)
, which is usually the lowercase name of the provider type. - For other provider types, you will need to use the provider’s name as defined on the data source record.
Removing stored OAuth access credentials¶
To remove stored OAuth access credentials for a particular service, call the following method:
Authentication Merge Variables¶
{{$Auth.BasicAuth}}
{{$Auth.Username}}
{{$Auth.Password}}
{{$Auth.Response.Body}}
{{$Auth.Response.Headers}}
{{$Api.Session_Id}}
{{$Apex.ClassName.Input}}
On the $Apex
merge variable¶
The $Apex
merge variable is used to retrieve values returned by an Apex class method. It can only be used within data sources where Skuid’s proxy is enabled.
The most common use case for this variable is to retrieve authentication secrets stored outside of Skuid’s secret store. This may be desirable for a variety of reasons, including:
- The secret is longer than 255 characters, which is too long to be saved within Skuid’s secret store.
- Your use case requires custom logic for determining the authentication token which is best handled in Apex.
- Your use case requires additional data or a nonce value, like the current timestamp, as a part of your secret request.
The sections below cover how to implement the skuid.Utils.MergeValueProvider
interface in Apex and how to access the Apex-provided value using proper merge syntax.
Note
We recommend having a developer fluent in Apex assist in using this feature while consulting Salesforce documentation.
Writing a compatible Apex class¶
To write a merge value provider class, you must properly implement skuid.Utils.MergeValueProvider
, which requires defining a getValue
method. It also must be declared using the global
access modifier so it can be accessed by Skuid.
Consider this basic example:
1 2 3 4 5 | global class SecretsValueProvider implements skuid.Utils.MergeValueProvider {
global string getValue(String[] keys) {
return 'secret';
}
}
|
The following links may be helpful depending on your use case:
Using the $Apex merge variable¶
To use the variable in a data source, write it in the following syntax:
{{$Apex.ClassName.Inputs}}
This uses two parameters:
ClassName
: The Apex class to access.For nested classes with
.
dots in their name, use double underscores (__
) in place of the dot.For example, to access the following fully qualified class name:
namespace.OuterClass.InnerClass
You would use the following merge syntax:
{{$Apex.namespace__OuterClass__InnerClass}}
Inputs
: (Optional) An array of inputs/keys which will be passed to thegetValue
function as an array of strings.For example, this merge variable:
{{$Apex.ClassName.Key1.Key2}}
Will pass in the following string array:
('Key1', 'Key2')
Whereas
{{$Apex.ClassName}}
will result in an empty string array (()
).
Why use double underscores in place of dots [[]]?¶
Because double underscores are not allowed in Apex class names (and thus would not appear in any class name), this convention means Skuid can access nested classes while retaining standard merge variable syntax.
Troubleshooting¶
Unknown merge value provider class: ClassName
This indicates the given Apex class was not found. This can happen because the class does not exist or because the class is not accessible to Skuid.
To resolve this error:
- Make sure there are no typos in the
$Apex.ClassName
portion of the merge variable. - Make sure the Apex class is declared using the
global
access modifier
- Make sure there are no typos in the
Class doesn't implement MergeValueProvider: ClassName
This indicates that the class was found, but it does not implement
skuid.Utils.MergeValueProvider
.To resolve this error, make sure the class implements
skuid.Utils.MergeValueProvider
correctly:1 2 3 4 5 6
global class SecretsValueProvider implements skuid.Utils.MergeValueProvider { global string getValue(String[] keys) { /* Apex code */ return 'secret'; } }
Encryption in Skuid¶
The following fields are stored encrypted in Skuid:
- Data Source (for org-wide credentials)
- Username
- Password
- Data Source Credentials (for per-profile or per-user credentials)
- Username
- Password
- Authentication Provider
- Client Id
- Client Secret
Skuid SFX encryption [[]]¶
Note
The following only applies to Skuid SFX.
For data sources that use Basic HTTP Authentication, Separate Authentication URLs, or an Authentication Provider, you can choose to store credentials within a Protected Custom Setting inside of Salesforce. As an extra layer of protection for these credentials, Skuid encrypts all credentials using 256-bit AES encryption. The encryption key can be configured within each individual org that stores credentials. Credentials can be specified on org-wide or a profile levels, or they can be entered on an individual user basis.
Note
As org-wide credentials and per-profile/per-user credentials are configured in different areas, they are encrypted as different objects. However, this does not affect their security or functionality.
Skuid SFX stores sensitive data in Protected Managed Custom Settings. This prevents direct access to the stored values (except via Skuid Managed Apex code). Certain fields on these Protected Custom Settings are also encrypted when written to the database and decrypted at run time. The objects/fields utilizing this feature are as follows:
- Encryption Settings
skuid__Key__c
This object stores the organization’s Master Encryption key. This key is itself encrypted with a separate key that Skuid manages. This provides an additional layer of security by avoiding storing the actual encryption key in plain text in an organization’s data.
- Data Source
skuid__Username__c
skuid__Password__c
- Data Source Credential
skuid__Username__c
skuid__Password__c
- Auth Provider
skuid__Client_Id__c
skuid__Client_Secret__c