K2Trust (also known as trust.k2.com) is used by K2 to handle claims authentication and Single Sign-On (SSO) with Azure Active Directory (AAD). It is a Relying Party Security Token Service (RP-STS) used to broker authentication requests between K2 servers and AAD STS.  The K2Trust URL is registered with Microsoft for use with K2 Apps.

Table of Contents

Articles in this Series

Why use a RP-STS for SSO when AAD already has an STS?

For K2 to provide integration with an Office 365 tenant along with SSO, an AAD application would have to be installed in the tenant’s AAD instance by a Global Administrator. The permission for SSO is set in the application’s manifest as well as the allowed redirect URIs. Since each tenant’s K2 instance would have different URLs for the various sites like Designer, Runtime and View Flow, a single application could not be used unless K2 provided a redirector to manage it. Providing an RP-STS enables K2 to automatically handle the setup and configuration of the authentication and claims infrastructure.

OAuth 2.0 authorization needed the same mechanism for SharePoint applications. This used a slightly different flow but was essentially the same design as AAD in that only one redirect URI could be registered per tenancy.

K2 created K2Trust to handle multiple redirect URIs and to remove the requirement that you install an app directly in your AAD instance (which, in turn, requires an active AAD subscription, which some customers do not elect to purchase).

Over time, the role of K2Trust was expanded beyond a simple RP-STS into a robust and secure authentication and authorization redirector. All communication with K2Trust happens over an encrypted, SSL connection.

There are two servers that currently serve as K2Trust:

  • West US: 104.45.215.52
  • West Europe: 191.233.88.131

Depending on the Azure traffic manager, you may be directed to either one of these based on latency, load, and failover. Most likely you will be routed to the geographically closest server but that is not guaranteed. This means that if you are constraining your K2Trust calls based on the IP address, you must add both of these IPs to your configuration. 

Authentication

K2Trust is an RP-STS that currently supports WS-* (WS-Trust, WS-Federation) standards to issue SAML tokens issued by the IP-STS associated with the RP's realm.

To learn more about RP-STS and IP-STS, please refer to the MSDN article What is an IP-STS and what is a RP-STS

WS-Federation

Any RP that uses the Windows Identity Framework (WIF) is able to use K2Trust as its STS and can be setup by consuming the federation metadata document located at the standard location on K2Trust:

https://trust.k2.com/federationmetadata/2007-06/federationmetadata.xml

WIF is used to generate the sign in and sign out message, depending on the request made, to the appropriate Identity Provider (IdP) STS in order to authenticate the user. The returned token is then issued and posted to the requesting RP.

Using Azure Active Directory for SSO

For SSO with AAD, an AAD application must be installed into a tenant’s AAD environment and trusted for SSO. This application has an AppIdUri which is the value for the realm of the RP that performs the login to AAD.

The application also contains the redirect URIs to which the STS will return the request once authenticated. The request is not honored if the reply URL (wreply) parameter does not exist in the list of redirect URIs of the application.

K2Trust acts as the RP-STS as the authenticated result is posted to K2Trust, which then posts that result to the requesting RP. In order to secure this communication, K2Trust persists its own list of relying parties that are allowed to authenticate to it (and therefore AAD). K2Trust encrypts and persists information to the K2Trust database, including information such as the tenant realm, relying party URLs, and the K2 application. This ensures that the tenant can be validated. No user information or tokens are ever stored in the database. For K2 Cloud & Appit environments, the information is stored during the onboarding process. For K2 Five & K2 blackpearl environments integrated with SharePoint Online, the information is stored when the SharePoint App Registration Wizard executes.

User information and tokens are NOT stored by K2Trust. These are persisted on the K2 server only.

The K2 Trust database is stored in SQL Azure and is only accessible from the K2Trust instance. The tenant admin's realm ID is retrieved from the authenticated SAML token and is unique per tenant.  The realm ID is used as a link to secure this flow. This ensures that the instance of the K2 app only redirects to the tenant ID.

The relying party is added once a tenant admin consents to the K2 App. The authenticated result is returned to K2Trust, which at that point trusts that the incoming user is authenticated against a specific realm. This is true because it is using the TenantId claim value and knows the relying party URL is valid. These URLs are bound to the RealmID and only a user that is a member of the specific AAD instance can then continue with the login.

Let's take a look at the K2Trust Authentication flow:

Image

  • Web in the diagram above refers to the K2 web sites: K2 Designer, SmartForms Runtime and View Flow
  • The SAML token in the FedAuth cookie is valid for 8 hours. Once expired it will initiate the authentication loop, which refreshes the token and creates a new valid cookie.  The cookie is valid until you delete it or explicitly sign out.
  • These flows happen over an SSL connection.

If the K2 App has not been installed in the AAD tenancy, the WS-Fed signin fails as the application does not have the permission to perform SSO.

OpenID Connect

OpenID Connect is a different standard that combines some of WS-Fed and OAuth 2.0 in order to create a single authentication/authorization experience that allows a single request to retrieve an identity token as well as an OAuth 2.0 (authorization) token. 

The K2 platform does not use OpenID Connect requests but rather standard WS-Fed sign in requests. K2Trust, based on the parameters in the request, retrieves the necessary information to build up an OpenID Connect request.

K2Trust then uses the AAD OpenID Connect flow to enable Common Consent (details of which are in Outbound Authorization an OAuth in K2). This allows you to give consent to a K2 App to allow SSO. The result is sent to the callback endpoint which then generates the appropriate SignInResponseMessage, which is then posted to the requesting client web app. K2Trust supports OpenID Connect but the K2-based web properties do not support it. Because of this, K2Trust uses JSON Web Token (JWT) classes to send back a WS-Fed token.

The end result is that the requesting web app uses the standard WS-Fed request but since K2Trust uses OpenID Connect, you are prompted for consent if the K2 App has not been installed in the AAD instance. Ultimately this results in the authentication loop completing successfully.

Let's take a look at the OpenID Connect flow:

Image

Security Token Service (STS)

The STS refers to the engine that validates and issues the claims token that will be consumed by a RP. This token is used to instantiate the ClaimsPrincipal which essentially authenticates the user with the web site (RP).

The K2Trust STS takes the ClaimsPrincipal received from the IdP-STS and generates a new ClaimsPrincipal. This is used to generate the SignInResponseMessage which is signed with the K2Trust certificate and issued to the RP.

If you want to claims-enable your web application using K2Trust, you can browse to the following endpoint: https://trust.k2.com/federationmetadata/2007-06/federationmetadata.xml

The STS also contains the class that generates the FederationMetdata XML that can be consumed by any WS-Fed compliant RP.

The FederationMetdata XML is also used to update the thumbprint of an RP since the certificate used to sign a token can expire or be revoked. If it does expire or is revoked, the RP needs to be updated and the FederationMetadata XML allows this to happen automatically.

Authorization

K2Trust supports OAuth 2.0 as an authorization standard. It acts like a redirector for the authorization flows.

K2Trust uses its list of relying parties, tenant realms and K2 client applications to validate the request from a specific K2 server to only allow matching requests to be completed.

As is the case with the AAD application, this requires a set of redirect URIs in order to perform SSO. OAuth requires a specific redirect URI to which it will issue the auth_code and oauth_token. This is done for security and is why K2Trust is required to be the broker between the real authorization server and the client. In order to ensure that K2Trust does not send the token to unsecured clients, it also keeps a list of relying parties to which it is allowed to issue the relevant auth_code and oauth_token.

When a request is made for an access token, K2Trust validates the client_id against the list of configured K2 application and, if a match is found, retrieves the K2 application details that it needs to perform the request, such as the AuthorizationEndpointUrl, TokenEndpointUrl, Client Secret, etc.

After it has been confirmed that the client has been configured for OAuth, it then initiates the correct authorization flow with the authorization server and completes the loop as necessary.

AppOnly (currently only supported with SharePoint Online)

K2Trust does not support issuing Application Only (AppOnly, a Microsoft term) access tokens without an existing access token. The reason for this measure is that any user with the knowledge of another AAD tenant could potentially request an AppOnly token from K2Trust without being a user in that particular tenant as there is no prior request (auth code or refresh token) with which to validate the user. This means that you must first make an authorized request by adding a valid access token to the request for an AppOnly token. Note that an AppOnly token request must be made with a valid user token for that realm.

The secret key for all client applications that have been configured for K2 is only contained on K2Trust and only when a request has been validated will the client secret be used to retrieve the access token.

Let's take a look at what happens when requests are made to trust.k2.com, first by looking at the Authorization Flow and second by looking at the Authorization Flow.

Authorization Flow

A normal authorization flow when a user requests an authorization code (response_type=code)

Example: https://trust.k2.com/authorize/oauth/2/request?client_id=2720c4fb-1a53-4f2f-8d7c-e059eeed11d8&response_type=code&redirect_uri=https://k2trusttest.appitdev.com/OAuthTest/AuthorizeCallback&resource=https://graph.windows.net

When there is a valid client ID and redirect URI:

  1. K2Trust retrieves the client (client_id)
  2. K2Trust retrieves the relying party (redirect_uri + client_id + realmID)
  3. K2Trust builds up the code flow url using the information from the client
    1. AuthorizationEndpointUrl
    2. Uses K2Trust url as redirect uri since that is the redirect uri that has been configured in the K2 App
  4. K2Trust saves the original redirect_uri and state in the secured Azure cache
  5. Normal OAuth flow takes place – an example of the return value below:

Example: https://trust.k2.com/authorize/oauth/2?code=AAABAAAAvPM1KaPlrEqdFSBzjqfTGBM-wwVJg3u_mXYQF7Il3KMkDPo8dCR2hy4vpn_EIr8s5QszlFCpoco6UK_qeylBMiL9YRNY7TygIua2SSHLalAhDta9uMjFLs7CqKAzWNRpFuLFf1uMMoqb8fgbDjTzmS7Pglf6ZS5atpX4KeUL5iFFlZUCl76Eu5xGQo_nTMgeiaUNSYX-pd_P8BeB1s7qd04Su-bE_A0i9cordx39wUJRVUMTWZ57l-WgDtTSPT6IgaZOXZUrgRq9p7mqEbtDErfaiV6tQRCMf9tHk00dxZQLKBvunD3KPX968F8qAJie5ERgTWdQGNcgo4xsQHNATAR0Ny1eUITV9Mo8TPgSsb7Pherh2EX5OiEYuEpeuwTTD7UCVZDNAKB0X2UbOmYop7UbiI4yEOAp6imiRo6I5ujADDp5ShHa1ADsoxKY4UNfm0prSAvp5szD7nJ651PuLt_YKOTQO8RP_NliqyNprMRLQOLYXsFk4DXxLQPo3g2MWYtGs5fB1WMUhnUjJu9lQNGEkW2UWEOAAK6OVw4jdFDTwsAa22_LL7c3HFVTJchETgF8s-

  1. K2Trust receives the code, gets the original redirect_uri and state and sends values to user

When there is an invalid client ID:

  1. K2Trust tries to retrieve the client based on the specified but does not find it
  2. Redirects to Error page "Bad Request: invalid_client_id "

When there is an invalid redirect URI:

  1. K2Trust tries to retrieve the client and finds the client in the database
  2. K2Trust tries to retrieve the relying party but does not find any redirect URI matching the specified value.
  3. Redirects to Error page "Bad Request: invalid_redirect_uri"

Access Token Flow

Use this access token flow diagram and explanation to discover how the authorization and authentication flow of a user requesting a K2 object, such as a form, SmartObject data, or a report, goes from the initial request, to the K2 site/server, through K2Trust (when the user is based in the cloud), and then to the auth services in AAD.

  1. User requests an OAuth token using the authorization code received from the previous flow.

Example: https://trust-dev.k2.com/token/oauth/2

Post data: AuthorizationCode=AAABAAAAvPM1KaPlrEqdFSBzjqfTGBTIFM1-b10iswQT8BP-IKabhEyEea3tpi82yHNUJOK21wzti0iCLkzQCMdWHyytO6jymUMZRi0a0DJlSM9soXINlQO7R4-8f3CivTnBXDoAcV0PRzDnlSJNqRvuXe79IBl8_UIj3anSYzsRTdqCU2qyIiILTojmL8cIU_V7h58Cc17yopgdMUeg3qOe9sx4dUf7E1n4GI01OFM92w6gfGW2BPInMcqPA3BR92cUOQHNr_6-OtZWT_e7qK7ZjP2pA6m_KWSn5sCzSE1Sivi9OEVOWuSNPRbydjeJLiyPFZeL0Ay9rrVrsabAj9iI2_fF81lArHmQC7L_2OONfu2nqlxh-1rUal6kmCRjqjbgC7YmSaPb7Y-E0XL65PcKjX_Q8enpxDLAFyV8jlp1RRhCkAu4f2m8L1NdkWFKBOtIYejUgBdRdC2Y0G1tngblLF4oxAj9X7RfighcMd6bDWdxLlzBcjbZNZG-r-xDz1oScZNK2L_76QIrR86UIoCPixUoVhxXpdX7rS25OFGWHp3FWw-oWRgFLWVDts4qfjLlRNU2C1Go7poiTCKqszUO_IgZZ3ZPQ59Pbor1HJ41L19FRPQgAA&State=uri%3Dhttps%3A%2F%2Fk2trusttest.appitdev.com%2FOAuthTest%2FAuthorizeCallback%7Ccid%3D2720c4fb-1a53-4f2f-8d7c-e059eeed11d8&TokenEndpointUrl=https%3A%2F%2Ftrust-dev.k2.com%2Ftoken%2Foauth%2F2&ClientId=2720c4fb-1a53-4f2f-8d7c-e059eeed11d8&ClientSecret=&RedirectUri=http%3A%2F%2Fk2trusttest.appitdev.net%2FOAuthTest%2FAuthorizeCallback&Resource=https%3A%2F%2Fgraph.windows.net

 

  1. K2Trust validates the post data.
    1. Check that a client is configured for the client_id
    2. Check that a replying party has been registered for the redirect_uri, client_id and realmID
  2. K2Trust replaces the redirect_uri with the trust redirect_uri
    1. Since the K2 App has been registered with K2Trust redirect_uri’s, K2 can only ask for tokens and have it issued to K2Trust.
  3. The received token is then posted to the relying party, and the K2 object is returned.

Image

Appendix: K2Trust Error Codes

Error Code

Error Id

HTTP Status Code

Message

Remedy

K2TSTS0000

server_error

 

500

 

An unhandled error has occurred.

 

K2TSTS10000

invalid_wsfedrequest

400

Incoming request is not a valid WS-Federation request

Ensure that the request is a valid WS-Federation sign-in request or sign-in response and that it contains all of the required parameters.

K2TSTS10001

invalid_signinrequest

400

An error occurred while processing a WS-Federation sign-in request

Details are in the message

K2TSTS10002

invalid_signinresponse

400

An error occurred while processing a WS-Federation sign-in response

Details are in the message

K2TSTS10003

invalid_signoutrequest

400

An error occurred while processing a WS-Federation Sign-out request

Details are in the message

K2TSTS10004

400

An error occurred while attempting to generate federation metadata

Details are in the message

K2TSTS10005

invalid_replying_party

400

Requested relying party realm '' is unknown.

There was a mismatch between the AppliesTo given in the token request and the realms configured in K2Trust.

K2TSTS20000

400

The version of OAuth used is not supported.

Ensure that the request is made for a supported OAuth version. Only OAuth 2.0 is supported.

K2TSTS20001

400

An error occurred while processing an authorization request

Details are in the message

K2TSTS20002

400

An error occurred while processing an authorization response

Details are in the message

K2TSTS20003

400

An error occurred while processing a token request

Details are in the message