Skip to Content

Ingress links

Developers may need to link to App Builder from external sources such as:

  • Other applications
  • Email messages
  • Portals
  • iframes

Such links may direct the user to the default application or to a specific application. They may allow the user to choose how to authenticate or initiate the sign-in process with a specific security provider. The developer can control these behaviors by constructing the links appropriately.

Typically, when linking to App Builder, developers will construct a URL to the App Builder root directory. The URL might look something like this:

https://example.com/App Builder/

This link assumes that App Builder is hosted in an App Builder directory beneath the web site root directory. In many cases, App Builder will be hosted at the web site root.

When a user follows such a link, App Builder will redirect the browser to the login form. However, if an external authentication provider has been configured as the Default Authentication Provider, App Builder will bypass the login form, redirecting the browser to the external authentication provider instead.

Regardless, once the user has successfully signed in, App Builder will determine the appropriate default application based on the user's privileges. App Builder will then redirect browser to the application's home page.

A "deep link" is a URL that points to a specific application or page. An example of a deep link might look something like this:

https://example.com/App Builder/app/Sales/Leads

In this example, Sales corresponds to the application name; Leads, the page name. Note that these are URL encoded as per RFC 3986, section 2 (https://tools.ietf.org/html/rfc3986#section-2).

App Builder supports deep linking. Specifically, developers can construct links that point to a specific application or page within App Builder. As with top-level links that point to the web site root, App Builder will automatically determine whether the user needs to authenticate, redirecting the browser to the login form or external authentication provider. Once the user has successfully signed in, App Builder will redirect the browser to the deep link URL.

The simplest way to construct a deep link is to surf to the target page. The browser's address bar will contain a URL that looks something like this:

https://example.com/App Builder/app/Sales/Leads?$activepanel=Leads&Leads.LeadId=123456

The portion of the URL starting with the question mark (?) is the query string. App Builder uses the query string to track selected panels and rows, filter and search criteria, etc. Remove the query string to construct the canonical URL to the page.

Query string used in URL

In building the exact page URL, App Builder does what it needs to maintain the entire context of your session. In general, there are different components of a given App Builder page that may end up included as part of the query string URL. Components ending up in the URL may include: Primary Keys, Page Name, Panel Name, and Control Name.

Tips to shorten URL

There are instances where App Builder generates a very long URL for Pages. In this section we will provide some general tips to consider to help shorten the URL.

  • Define your Primary Keys. App Builder will use in the URL what it sees as PKs to keep track of selected records, and sometimes App Builder will use all or most of the columns if left implicit in the rule. For this reason, always make sure you find the actual unique columns needed to identify your record.

    • If you decide to use a longer string as your Primary Key, know that will take up more space in the URL
  • Keep your Names short for Page, Panels, and Controls. If you require them to display as longer name values, use the Label field (which will not be included as part of the query URL)

In addition to the tips listed, IIS settings may be worth reviewing by your System Administrator. IIS places some limitations on URL length by default, and some settings are configurable to allow for longer URLs. Settings to review include:

  • maxAllowedContentLength - Maximum file upload size. Defaults to 30000000
  • maxUrl - Maximum URL length. Defaults to 4096
  • maxQueryString - Maximum URL query string length. Defaults to 2048

See the Microsoft article on Request Limits <requestLimits> for more information.

Warning

Changing an application or page name will break existing deep links.

Authentication

As noted above, App Builder will automatically redirect anonymous users to either the login form or an external authentication provider. In most scenarios, this is the desired behavior. However, there may be situations which require the user to sign in with a specific security provider. Examples include:

  • The deep link points to a page that requires a specific authorization. For instance, the target page may display data retrieved from Salesforce. In which case, the user will need to authenticate with Salesforce before accessing the page.
  • The user has already authenticated with a single sign-on (SSO) provider. For instance, the user may follow a link within a portal. To access the portal, the user signed in with Active Directory Federation Services (ADFS). Assuming App Builder is also configured to authenticate users via ADFS, the user may effectively bypass the login form when following the link.

Challenge URLs

To force users to authenticate with a specific security provider, the link must be constructed in such a way as to trigger a challenge. The following example demonstrates a challenge for a specific authentication provider:

To force users to authenticate with a specific security provider, the link must be constructed in such a way as to trigger a challenge. The following example demonstrates a challenge for a specific authentication provider:

We'll refer to this as the challenge-url. The challenge-url is constructed of:

<vinyl-root>/service/authentication/external?provider=<provider-name>&returnUrl=<response-url>

Where:

  • <vinyl-root> - This is the absolute URL to the App Builder web application root directory. It does not include the trailing slash. In this example, vinyl-root is https://example.com/App Builder.
  • <provider-name> - This is the security provider name as defined within App Builder. In the example above, provider-name is SAML. Note that provider-name must be URL encoded.
  • <response-url> - This is the App Builder web application's callback URL. It's not the deep link. The response-url needs to be URL encoded.

In the example above, decoding the response-url produces:

https://example.com/App Builder/auth/authenticated?returnUrl=%2Fapp%2FSales%2FLeads

The response-url is composed of:

<vinyl-root>/auth/authenticated/?returnUrl=<relative-link>

Where:

  • <vinyl-root> - Absolute URL of the App Builder web application root. See above.
  • <relative-link> - This is the App Builder web application root-relative portion of the deep link. It is URL encoded.

In the example above, the relative-link is:

%2Fapp%2FSales%2FLeads

Decoding the relative-link gives us:

/app/Sales/Leads

As noted above, this is relative to the the App Builder web application root directory (i.e. vinyl-root).

Constructing a challenge URL

To construct a challenge URL, we need to reverse the process.

Step 1) Start with the deep link and remove vinyl-root to get relative-link. It should begin with /app. URL encoded the relative-link.

Step 2) Construct the response-url from:

<vinyl-root>/auth/authenticated/?returnUrl=<relative-link>

URL encode response-url.

Step 3) Construct the challenge-url from:

<vinyl-root>/service/authentication/external?provider=<provider-name>&returnUrl=<response-url>

Fiddle for generating the challenge URL

The following JSFiddle can be used to generate a challenge URL:

https://jsfiddle.net/8s8gkufh/1/

HTML

Link:<br>
<input data-bind="value: link"><br>
Provider<br>
<input data-bind="value: provider"><br>
Challenge URL:
<input data-bind="value: challenge" readonly>

JavaScript

function ViewModel() {
  this.link = ko.observable("http://example.com/App Builder/app/Northwind");
  this.provider = ko.observable("SAML");

  var startOfRelativeLink = ko.computed(function() {
    return this.link().indexOf("/app");
  }, this);

  var root = ko.computed(function() {
    return this.link().substr(0, startOfRelativeLink());
  }, this);

  var relativeLink = ko.computed(function() {
    return this.link().substr(startOfRelativeLink());
  }, this);

  var response = ko.computed(function() {
    return root() + "/auth/authenticated?returnUrl=" + encodeURIComponent(relativeLink());
  }, this);

  this.challenge = ko.computed(function() {
    return root() + "/service/authentication/external?provider=" + encodeURIComponent(this.provider()) + "&returnUrl=" + encodeURIComponent(response());
  }, this);
}

ko.applyBindings(new ViewModel());