Using the iOS SDK to Consume the Authentication API

Using the iOS SDK to Consume the Authentication API

tutorials

What Is the Hypermedia Authentication API?

The Hypermedia Authentication API is a feature of the Curity Identity Server. It enables clients to leverage OAuth and OpenID Connect and Curity’s powerful authentication engine straight from client applications — without the need of a browser. If you want to learn more about the Hypermedia Authentication API, check out the overview here.

It’s All About Security

The browser typically plays a vital role in OAuth and OpenID flows — it makes them more secure. Browser redirects ensure the Authorization Server delivers data to the proper client, and not to an impersonator. Thus, removing the browser from OAuth and OpenID flows may at first seem a bit reckless. As we now use an API to fulfill a vulnerable authentication and authorization flow, we require another method to make sure that the client calling the API is indeed allowed to do so.

We’ve added two security features to the Curity Identity Server to ensure the Authentication API process is just as secure as browser flows. These new security features are:

  • Client attestation.
  • Usage of proof of possession tokens.

Client Attestation

Client attestation is done by verifying the running application’s package ID and the signing credentials. This is processed by the Android Operation System or iOS and bound to a cryptographic key pair. After a positive attestation, the client (the mobile app) is issued a Client Attestation Token (CAT) in the form of a JWT. The concrete implementation of the attestation is out of scope for this article, but what is important to note here is that client attestation asserts a few things about the client that calls the Authentication API:

  1. The app was correctly signed with the credentials configured in the Curity Identity Server for the associated OAuth client. This means the app has not been tampered with. For example, it hasn’t been decompiled, had its code changed, and recompiled into a malicious client. What is essential when using these features is that decompilation cannot provide any information that could help create an impersonated client.
  2. The app runs in a safe environment, that is, on a system that has not been rooted. Otherwise, it wouldn’t be possible to perform the verification described above securely.

Demonstration of Proof-of-Possession

Proof-of-Possession tokens are another way to use access tokens. The most common ones used in APIs are Bearer tokens. Bearer tokens work a bit like cash — any client who posses a Bearer access token can successfully call an API. Proof-of-Possession tokens behave more like credit cards — only legitimate owners of these tokens can use them to access the API. This further increases the security of the communication. Even if an access token is stolen, it can’t be used by another party.

The Hypermedia Authentication API uses a standard for Demonstration of Proof-of-Possession. By adopting this standard, access tokens used to access the Authentication API are bound to a private key that only the legitimate client possesses.

The SDKs for Hypermedia Authentication API

Obtaining CATs and using DPoP to secure requests to the API is a security-sensitive process and quite complicated to implement. The method of obtaining a CAT requires a few different steps, and the DPoP standard requires the client to generate proper DPoP headers for every request. To facilitate the usage of these crucial security components, Curity has released a simple SDK to help you leverage the Hypermedia API.

Prerequisites for using the API

To call the API from an iOS app, make sure of the following:

  1. Use at least version 6.2.2. of the Curity Identity Server.

  2. You will require an iOS attestation policy. To add one, follow the instructions below:

    • Open the Facilities menu in the top right corner of the admin UI and scroll down to Client Attestations.
    • Click on the New button next to iOS policies.

new attestation

  • Enter a suitable name for the policy and click Create.

new attestation name

  • Choose the appropriate mode. production mode tells the Curity Identity Server to validate the app against its release signing settings. Choosing non-production will validate the app against the debug signing settings. In some rare cases it might also be necessary to overwrite Apple’s Certificate Chain, but normally you shouldn’t need to use this setting. Close the dialog once you choose all the settings.

ios attestation configuration

  1. You will also need a client with the API capability which uses the iOS attestation policy.

    • Go to Profiles -> Token Service -> Clients, and edit the client of your choice.
    • In the Capabilities section, make sure your client has at least these two enabled: Hypermedia Authentication API and Code Flow. Use any URL for the redirect URL (e.g. https://localhost) and choose no-authentication as the Client authentication method.
    • Scroll down to the Client Application Settings tab and open the Advanced section. Enable the Attestation, and select ios as attestation type. Enter your App ID following the instructions available next to the input field and choose the Attestation Policy that you’ve previously created.
    • If you want to test or develop the app using a simulated device turn on the Disable Attestation Validation option. When this is on, the Attestation will still be performed by the client and server, but the server will not validate the attestation. Attestation functionality does not work on simulated iOS devices, so you have to enable this option when using a simulator. Remember not to use this setting for production clients!

client attestation settings

Remember to commit all the changes made to the configuration.

Note that you can also use the configuration CLI or RESTCONF API to set these settings.

Using the SDK in an iOS app

You can obtain the SDK from the Curity Github. You can add it to your project either by using the Swift Package Manager or through CocoaPods.

You can add the following to your Package.swift file:

    .package(url: "https://github.com/curityio/ios-idsvr-haapi-sdk-dist")

If you’re not using the Package.swift file, and you prefer to add the dependencies directly in Xcode, follow these steps:

  • Go to project properties in your Xcode, to the Swift Packages tab.
  • Click the + button below the table.
  • Enter https://github.com/curityio/ios-idsvr-haapi-sdk-dist to the input field and click Next.
  • Choose the desired version policy (you can leave the default settings).
  • Click Finish to add the dependency.

Add the following code to your Podfile. Remember to change the <Your Target Name> to the name of the target used in your project.

platform :ios, '14.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'IdsvrHaapiSdk'
end

Install the dependency by running pod install.

The SDK exposes an object HaapiTokenManager, which is capable of creating an HTTP client. The token manager accepts some configuration options and is responsible for obtaining a Client Attestation token and creating proper DPoP headers. The client is configured to enrich requests with the necessary tokens and headers.

Below is an example of calling the API with the SDK. Note that no additional work concerning Client Attestation or DPoP is needed. Thanks to the SDK, these are still used in the communication with the API.


import IdsvrHaapiSdk
...

let haapiManager = HaapiTokenManager.Builder(
    tokenEndpoint: URL(string: "https://idsvr.example.com/oauth/v2/oauth-token")!,
    clientId: "demo-client"
).build()

let haapiClient = haapiManager.createClient()

let authorizationURL = URL(string: "https://idsvr.example.com/oauth/v2/oauth-authorize?client_id=demo-client&response_type=code&redirect_uri=https://localhost")!

var request = URLRequest(url: authorizationURL)
request.httpMethod = "GET"

haapiClient.performDataTask(for: request) { result in
    switch result {
        case .success(let responseAndData):
            guard let data = responseAndData.data else {
                return
            }

            print(String(decoding: data, as: UTF8.self))
        case .failure(let error):
            print(error)
    }
}

Conclusion

With the SDK, you can start using the Authentication API in minutes without delving into the specific details of the API’s security enhancements. Thanks to this SDK, you can quickly focus on creating user interfaces.

To learn more about implementing clients that consume this API, have a look at the Authentication API documentation.

If you need help setting up the API or SDK, or have any other questions or comments, please do not hesitate to contact us.

Let’s Stay in Touch!

Get the latest on identity management, API Security and authentication straight to your inbox.

Keep up with our latest articles and how-tos using RSS feeds