Integrate Okta with Device Posture Provider
By integrating Okta with external services for device posture data, you can use device signals from these external identity providers (IdP). These signals enhance the security posture when you configure robust device posture requirements in both device assurance and app sign-in policies.
The Device Posture Provider feature uses SAML-based integration for seamless communication. The process begins with Okta sending a SAML request to your designated external device posture IdP. In response, the IdP returns a SAML assertion, which is a secure XML document that contains device posture attributes. These attributes are then available for you to define and enforce granular app sign-in policies. Only devices that meet your specified security standards can access the resources protected by Okta. Due to this integration you can create dynamic and adaptive access controls based on the real-time security status of end user devices.
Prerequisites
- Enable these features from the Admin Console: Device Posture Claims Mapping and Device Posture Provider.
- You need to configure an external SAML or OpenID Connect (OIDC) IdP as a compliance service to provide device posture information to Okta. See the SAML assertion data contract or OIDC data contract for details on the expected assertion or token format. After the device posture IdP sends data in the correct format, you can proceed with the Okta configuration.
Configure the device posture IdP in Okta
-
In the Admin Console, go to .
-
Click Add identity provider.
-
Select either the SAML 2.0 or OpenID Connect IdP and click Next.
-
Configure the IdP. See Create an Identity Provider in Okta for SAML 2.0 or OpenID Connect.
For IdP Usage: Select Device posture provider.
Enable the device posture IdP as a device assurance provider
-
In the Admin Console, go to .
- On the Endpoint security tab, click Add endpoint integration.
- Select Device posture provider.
- Select the platform.
- Save the configuration.
Use device posture IdP signals for a device assurance policy
You can create or modify device assurance policies to incorporate other signals from your IdP due to its integration with the Device Posture Provider. See Add a device assurance policy.
This integration allows for more granular assurance conditions in your policy rules:
- Compliant: The device adheres to the security standards and rules set by the external security system.
- Managed: The device is under the organization's IT or security team's control and oversight, as indicated by installed management agents or software.
After you configure your device assurance policy, you can integrate it into any app sign-in policies. See Add device assurance to an app sign-in policy.
If your global session policy configuration requires a password, the Sign-In Widget prompts users for both username and password before redirecting to the device posture IdP.
Configure the app sign-in policy rule that requires device posture claims to have the highest priority. Target-specific users by applying conditions like Group, Platform, or Network Zone.
SAML assertion data contract
Okta requires a specific data contract from the device posture IdP.
- Okta uses a new namespace: urn:okta:saml:2.0:DevicePosture
- This schema sends Device elements under AuthnStatement/AuthnContext/AuthnContextDecl/AuthenticationContextDeclaration/Extension
- A SAML response example is provided: Copy
<?xml version="1.0" encoding="utf-16"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="urn:okta:saml:2.0:DevicePosture" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Device">
<xs:complexType>
<xs:sequence>
<xs:element name="Posture">
<xs:complexType>
<xs:sequence>
<xs:element name="Fact" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="Name" use="required" />
<xs:attribute type="xs:string" name="Value" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="Attestation" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="Type" use="required" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="ID" />
<xs:attribute type="xs:string" name="Vendor" />
<xs:attribute type="xs:string" name="Model" />
<xs:attribute type="xs:string" name="OS" />
<xs:attribute type="xs:string" name="OSVersion" />
</xs:complexType>
</xs:element>
</xs:schema> -
Okta sends a SAML request to the IdP, which includes urn:okta:saml:2.0:DevicePosture as the minimum requestedAuthnContext.
An example of a SAML request sent by Okta to the device posture IdP is provided:
Copy<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://www.okta.com/sso/saml2/0oa6nxbvzJ7pgD2sk2o4" Destination="https://www.example.com/sso" ID="id259293517205908671989782748" IssueInstant="2018-08-14T22:15:29.753Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://www.okta.com/saml2/service-provider/spqunojxmhwsxjdesder</saml2:Issuer>
<saml2p:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" />
<saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
<saml2:NameID>
user@example.com
</saml2:NameID>
</saml2:Subject>
<saml2p:RequestedAuthnContext Comparison="minimum">
<saml2:AuthnContextClassRef xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">urn:okta:saml:2.0:DevicePosture</saml2:AuthnContextClassRef>
</saml2p:RequestedAuthnContext>
</saml2p:AuthnRequest> -
The device posture IdP sends a SAML response to Okta. The response includes device checks within the Extension tag, structured according to the schema. A required claim is <Fact Name="IsManaged" Value="true" />. Other claims are optional. You can include them for more context.
An example of a SAML response sent by the device posture IdP to Okta is included:
Copy<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://www.okta.com/sso/saml2/0oa26ezzJ73dyVy9y2o4" ID="_b77266a5f22f521f3b7d9df984e357e0" InResponseTo="id241879184953548991293661746" IssueInstant="2018-07-25T18:31:46.480Z" Version="2.0">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://www.example.com/metadata/idp.xml</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_2bc8c149c66f6d00cb9ba3200a3d5bd8" IssueInstant="2018-07-25T18:31:46.480Z" Version="2.0">
<saml:Issuer>https://www.example.com/metadata/idp.xml</saml:Issuer>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" NameQualifier="https://www.example.com/metadata/idp.xml">user@example.com</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="id241879184953548991293661746" NotOnOrAfter="2018-07-25T18:35:06.480Z" Recipient="https://www.okta.com/sso/saml2/0oa26ezzJ73dyVy9y2o4" />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2018-07-25T18:31:31.480Z" NotOnOrAfter="2018-07-25T18:35:06.480Z">
<saml:AudienceRestriction>
<saml:Audience>https://www.okta.com/saml2/service-provider/spcondtdepbkuyqvmrzi</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2018-07-25T18:31:46.480Z" SessionIndex="_00c85fbbdec2247daa24a20dfa9c2e70">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:okta:saml:2.0:DevicePosture</saml:AuthnContextClassRef>
<saml:AuthnContextDecl>
<AuthenticationContextDeclaration xmlns="urn:okta:saml:2.0:DevicePosture">
<AuthnMethod>
</AuthnMethod>
<Extension>
<Device ID="98bcb804e611de8fb0824b8dbaccfe3cc63171b4" Vendor="Apple" Model="iPhoneX" OS="iOS" OSVersion="10.2" xmlns="urn:okta:saml:2.0:DevicePosture">
<Posture>
<Fact Name="IsManaged" Value="true" />
<Fact Name="IsCompliant" Value="false" />
<Attestation Type="iOS">eyJhbGciOiJIUzI1NiJ9.eyJp…</Attestation>
</Posture>
</Device>
</Extension>
</AuthenticationContextDeclaration>
</saml:AuthnContextDecl>
</saml:AuthnContext>
</saml:AuthnStatement>
</saml:Assertion>
</samlp:Response> -
Okta returns an error, urn:oasis:names:tc:SAML:2.0:status:AuthnFailed, if the device posture IdP is unable to verify that the device is managed or trusted.
Copy<Status>
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder">
<StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:AuthnFailed" />
</StatusCode>
<StatusMessage>DEVICE_NOT_MANAGED</StatusMessage>
<StatusDetail>Kerberos NEGOTIATE failed or was canceled by the user.</StatusDetail>
</Status>
OIDC data contract
For an OIDC IdP, the standard sources of claims are the ID token and the UserInfo response from the IdP. The IdP adds the following claims to the ID token:
device_context: {
managed: true,
compliant: true,
externalId: "123"
}
