Protecting Okta App Sign-In with SGNL

Introduction

Protected Systems are applications, services, or infrastructure that you want to protect with SGNL. In this guide, we’ll describe how to achieve fine-grained access control at sign-in time with Okta and SGNL, enabling the right amount of access to applications and infrastructure connected to Okta. If you’d like to learn more about whether fine-grained Sign-In Policies with Okta and SGNL is right for your enterprise, visit our Securing AWS Blog or watch the video below to learn more.

With this integration, Okta need not know about the policies, systems of record, or any of the data in SGNL - it simply needs to pass to SGNL:

  • Who/What is requesting the access (The Principal)
  • (Optional) What is attempting to be accessed (The Asset)
  • (Optional) What operation is being attempted on the asset (The Action)
  • An access token that ensures the Protected System is a legitimate caller into SGNL

Prerequisites

  • An Okta Tenant
  • A SGNL Client
  • A SGNL User Account with Admin privileges
  • At least 1 Okta system of record integrated to SGNL, containing principals and (optionally) assets that will be evaluated in access evaluations
  • (Optional) 1 or more policies that you want assigned to the integration

Creating a Protected System in SGNL

  1. Log-In to your SGNL Client with an Admin Account
  2. From the left navigation pane, select Protected Systems and Add, or simply click Add from the SGNL Dashboard
  3. Select ‘Okta’ from the Identity Providers category in the list of integrations
  4. Give your integration a descriptive display name and description
  5. Specify the Default Policy to be applied to your App
    • Allow: If no policies provide a decision for an access request, SGNL will respond to the access request with an Allow decision
    • Deny: If no policies provide a decision for an access request, SGNL will respond to the access request with a Deny decision
  6. Next, you’ll need to configure which identifier Okta is using to describe your user/principal
    • This is likely your Okta user’s email address or login name. This should be in the format of the Principal ID of the user that will request access to the Protected System.
    • e.g. If an Okta user will be requesting access to this Protected System with the Principal ID as their email address, the principal identifier should be the Okta email address.
  7. You’ll also need to define the identifiers for the types of Assets that you are looking to protect
    • This might be app identifiers sourced directly from Okta, or something more granular within one of your other Systems of Record
  8. Once configured, click Continue to save your configuration and move on to other configuration steps

Configuring Authentication

  1. Authentication ensures that only authorized systems can make requests into SGNL, as well as verifying the identity of an integration in order to effectively evaluate Policies - to access Authentication settings, open your AWS protected system and select the Authentication tab

    SGNL - Authentication

  2. Click Generate Token

  3. Give your token a descriptive name so that you know how it’s being used in the future and click to Generate Token

    SGNL - Generate Token

  4. On the next screen, copy the token - this will be used by Okta to make access requests to SGNL using the SGNL Access Service API

    Note: The value of this token is not available again after this screen, so ensure you securely store it for steps later in this guide

    SGNL - Token

Integrating Okta Hooks with SGNL

Integrating SGNL with Okta, for the purposes of securing AWS or any Application, relies on Okta Inline Hooks. Okta Inline Hooks enable Okta to make an outbound request that can be routed to SGNL, in order to determine whether a user should have access to a specific application at that point in time, or what roles, claims, or tags to include in their SAML assertion

A simple example of this in action is using Okta Hooks to ask whether a user can access a specific customer’s data in AWS for a given session. In this scenario, SGNL Customers have found that PrincipalTags offer the greatest level of flexibility and dyamism, when combined with existing AWS roles, to dynamically specify an individual principal’s (user, service, robot, etc) permissions for a given session.

AWS provides the flexibility to enable Principal Tags to be used directly in conjunction with other policies that might already exist in AWS, and enables interleaving the tag directly into a resource name.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::sensitive-prod-${aws:PrincipalTag/customerId}*"
        },
      ...
    ]
}

To get the appropriate set of access for a given session (and consequently the necessary tag), an inline hook is routed to SGNL at authentication time. The hook specifies the Customer ID for which the user is requesting access.

SGNL’s Access Service responds with a determination whether the acess to a specific customer is allowed for a given session:

{
    "decisions": [
        {
            "action": "access",
            "assetId": "{{customerId}}",
            "decision": "Allow"
        }
    ],
    "evaluationDuration": 8,
    "issuedAt": "2023-06-22T23:49:32.087875656Z",
    "principalId": "alice.wu@sgnl.ai"
}

If Access is Allowed, the Customer’s ID is packaged into the Okta SAML Assertion as a PrincipalTag and then the user is redirected to AWS to be signed in. At policy evaluation time, AWS inspects the Principal Tag and appropriate policy, determining whether the principal should be allowed to access a given resource.

At this point, it’s likely that all decisions will either be Allow or Deny, based on the Default Decision you’ve selected for the Okta Integration - if that’s the case, you’re ready to start assigning policies.

Assigning Policies

  1. Once the Okta integration is created, you can start assigning versions of Policies - to get started, select Policies from the tabs in your newly created integration

    SGNL - Policies

  2. Select ‘Assign Policies’

  3. Select:

    • The Policies you want to apply to the integration with the check box
    • The version of the Policy you want applied

    SGNL - Select Policies

  4. Click Next once you have the Policies and Versions configured as is appropriate

  5. Select the Enforcement mode for the Policies you chose in the previous step

    • Simulated: Policy Versions that are being simulated will only log their access decision in the SGNL logs and will not impact the access decision that SGNL hands back to an integration. Simulated policies are useful for performing what-if analysis of new policy versions as well as debugging policy changes.

      Note: It’s considered best practice to start with policies in Simulated mode, to verify that policies have been created an applied as expected

    • Enforced: Policy Versions that are being enforced will impact the access decisions that SGNL hands back to an integration. Enforced Policies will determine access for an integration

    SGNL - Set Enforcement

  6. Select your desired Enforcement mode and select Assign

  7. Versions of Policies will now be Assigned to your integration

    SGNL - Policy Assignments

Configuring Transforms

SGNL makes it incredibly easy to integrate the SGNL Search API with Okta, enabling dynamic roles, claims, authorization decisions, and more to be handed back to the IdP at App SAML sign-in time.

Getting Started

We do that through Transforms. You can find Transforms in the Protected Systems page. To integrate your Okta Protected System (or a Protected System that uses Okta for SSO):

  1. Select the Protected System
  2. Start by going to the Settings tab, and ensure that the Asset(s) being returned in the Request Configuration section are those that you want handed back to Okta during SSO
  • Note: Transforms only manipulate the response provided by the search API for the chosen Protected System, they don’t allow additional querying/extraction of data from the request, from the SGNL Graph, or other sources
  1. At this time, you might want to make a request to the search API to ensure that you’re returning the data you expect (or that your users actually have access to the data you expect)
  2. Once you’re happy that policies are request configuration are correct, select the Transforms tab in the Protected System
  3. In this example, we’re going to configure a Search Transform using Okta, you first need to configure the fields to map from the request, SGNL uses JSONPath to find the right values in Okta JSON request, or you can enter your own static values just by typing them in as-is – a sample request can be found in Okta’s Help Documentation, some sample values are provided in the console via the (+) Icon, including:
  • {$.data.context.user.profile.login} –> Id (SGNL Principal Id)
  • {$.data.context.request.ipAddress} – ipAddress (Principal’s IP Address)
  • SGNL doesn’t provide recommendations for the action context – if you’re policies don’t require an action, feel free to leave this blank, otherwise you can extract data out of Okta’s request, or provide your own static value, like sign-on

Transforming the Response

We provide significant flexibility in how to transform the response to Okta - before you get started, a couple of things to note:

  • SGNL provides both Add and Replace operations for the response to Okta – Okta’s inline hooks require that if you’re sending a Replace operation, that there is already a claim in the Path you are specifying, no claim to replace will cause Okta to fail, therefore Add is recommended in most scenarios.
  • You can add as many transforms as you want to the response, though they will all have to share the same operation type
  • You can use parameters across any number of attributes on the asset returned, though you cannot choose arbitrary attributes across multiple returned assets
  • SGNL’s parameter syntax takes the format of “{$.<entity or node name>.<attribute name>}”

To configure the response transforms:

  1. Select the first asset you want to add Transforms for (i.e. When this asset is returned from the Search API, how do you want to transform the response back to Okta)
  2. SGNL will automatically generate a name for use in the Path and Value parameters, but change this to whatever suits your needs, it’s used only in this configuration
  3. In the Path field, specify the path where you want to add or replace a Claim, some common examples from other SGNL Customers include:
  • AWS Role Claim Path: /claims/https:~1~1aws.amazon.com~1SAML~1Attributes~1Role
  • Static AWS Principal Tag Path: /claims/https:~1~1aws.amazon.com~1SAML~1PrincipalTag:cost-center
  • Dynamic AWS Principal Tag Path: /claims/https:~1~1aws.amazon.com~1SAML~1PrincipalTag:{$.sfdcAccount.Id}
  1. In the Value field, specify the value of the claim that you want passed in this path, while you’re testing, this could just be a static string, but SGNL’s customers often use one or more parameters to configure the returned value, some examples:
  • Say you had a simple deployment in AWS with only your Okta IdP, and you wanted to dynamically assign roles, you might use an AWS IAM Role as the asset, and the arn as the attribute that you attach to your IdP string, e.g. {$.AWSIAMRole.arn},arn:aws:iam::111111111111:saml-provider/Okta-IdP
  • You might also have the whole ARN stored in the SGNL Graph, in that case you could simply return a single parameter without any extra detail, e.g. {$.AWSPermittedRole.arn}
  • A slightly more complex deployment might use the accountId from the AWSIAMRole to dynamically populate the information, e.g. {$.AWSIAMRole.arn},arn:aws:iam::{$.AWSIAMRole.account}:saml-provider/Okta-IdP
  1. Once you’re done configuring, you can hit save, this will allow you to use the SGNL Search API with the query parameter transform=true, e.g. https://access.sgnlapis.cloud/access/v2/search?transform=true
  2. You can now follow Okta’s instructions to configure the Inline Hook, using the address above as the target for the hook, and the authentication token you generated in SGNL
  3. Once configured, you can test the hook in Okta using Preview and in SGNL for Assets that have been allowed, you’ll see a log entry in the Access Logs.

Configuring Actions

As part of the SGNL CAEP Hub, Okta can be configured to receive Okta User and Device Risk events from SGNL, as well as standards-based CAEP Events. Follow the steps below to configure Okta to enable this integration.

Configuring Okta

To configure the API Integration:

  1. Login to the Okta Admin Console as a user with permissions to Create New API Integrations
  2. In the left-nav, select Applications and API Service Integrations
  3. From the list of available integrations, select sgnl (CAEP Hub)
  • Note This integration is different to sgnl which has only read permissions to Users and Groups, to be used when configuring a System of Record
  1. Selecting this integration will ask you to consent to the permissions granted in the below scopes:
  • okta.users.manage: The SGNL CAEP Hub can be configured to Suspend and Activate Users in Okta, based on events from other systems in your enterprise
  • okta.sessions.manage: The SGNL CAEP Hub can revoke user sessions, based on CAEP Messages or relevant business events
  • okta.userRisk.manage: If SGNL or a third-party provider connected to SGNL notices a change in User Risk, SGNL can broadcast that to Okta using User and Device Risk APIs
  • okta.securityEventsProviders.manage: To configure SGNL to send Shared Signals messages to Okta, we need to first establish a Security Event Provider – this scope will enable you to create that configuration – note that SGNL does not use this permission outside of initial configuration
  1. Click Install & Authorize on the consent screen
  2. Copy your Client Secret and store it temporarily somewhere safe, then clock Done
  3. Copy your Client ID, you’ll need this in a moment

To configure the Shared Signals Provider:

  1. In the Admin Console, go to SecurityDevice Integrations.
  2. Click the Receive shared signals tab.
  3. Click Add stream.
  4. Enter SGNL and your client name as the integration name, or a name of your choice (e.g. sgnl-acmeCorp)
  5. Specify the Issuer URL and JWKS (JSON Web Key Set) URL:
  • The SGNL well-known endpoint, for all clients this is: https://console.sgnl.cloud/api/config/metadata/v1/.well-known/ssf-configuration
  • The issuer, for all clients this is https://sgnl.ai
  1. Click Create. Refer to Okta’s Documentation for more details on configuring an Okta Shared Signals Framework Receiver.

Configuring SGNL

  1. From your Okta Protected System (with a type of at least Okta-1.0.0), select Actions
  2. Specify the Address for the Action, for now this can just be your Okta URL, e.g. https://{{YourOktaOrg}}.okta.com
  3. Specify Client Credentials as your Authentication method, and enter the Client Id and Client Secret you copied above
  4. You can specify all, or a subset of the following scopes depending on your use-case and our usage of the scopes as detailed above okta.users.manage okta.userRisk.manage okta.sessions.manage okta.securityEventsProviders.manage
  • i.e. if you don’t have an intention to revoke user sessions from Okta, you may not need the okta.sessions.manage scope – remember that even SGNL should be granted the minimum required privilege to achieve your business goals
  1. Specify your Okta Token URL, an example might be https://{{YourOktaOrg}}.okta.com/oauth2/v1/token
  2. The Audience can be left blank, and SGNL will auto detect the appropriate Auth Style

Creating your first action

From within SGNL you can configure any change in the graph to trigger actions that are directed to downstream systems. In an example scenario, you may want to trigger an Okta User Session Risk event when an end-user’s Azure AD Risk level is High. To complete this example integration, we assume someone has already configured Azure AD/Entra ID as a System of Record in SGNL:

  1. Select CAEP Hub from the SGNL nav
  2. Select Triggers
  3. Create a new Trigger:
  • Give the Trigger a Name and optionally a Description
  • Select Azure AD User and Okta User as the Nodes
  • Select the SameAs relationship between the AzureAD User and the Okta User
  • Select the Condition where riskLevel is equal to “High”
  • Save the Trigger
  1. Create a new Rule
  • Give the Rule a Name and optionally a Description
  • Select the Trigger you just created
  • Select the option for when the ‘Matches Trigger Scope’
  • Click the button to ‘Select an Action’
  • Choose ‘Okta’ and the ‘Okta User Risk Change Transmitter’ Action
  1. Configure the required and optional fields
  • The subject should be the Okta User: e.g. {"user":{"format":"email","email":"${.OktaUser.profile__email}"}}
  • The audience will be your Okta Organization: e.g. “https://acmecorp.okta.com
  • Specify an optional reason for the admin and user, as well as other fields that may be relevant Note These fields an be plain text, or can be parameters using the + button to select fields on the various nodes you’ve selected
  1. For this and other Okta Proprietary events, select Address inside of the Action, and enter the Okta security-events endpoint, e.g. https://acmecorp.okta.com/api/v1/security-events-providers
  2. Save the Rule

That’s it. Once you’ve finished configuring your rule, the next time a User’s risk is heightened in Azure AD, SGNL will send Okta a User Risk Change event.