Skip to main content

SSO Integration in IOS

Trust SSO - iOS#

Description#

TrustSSO allows client applications to fetch and update transactions and their different matters & present users different kind of authentication methods based on their needs.

Table of contents#


Implementation#

Easiest way to install TrustSSO is by using Cocoapods within just a few steps:

  1. Initialize cocoapods in your project (if it's not already done):
pod init

this would generate a Podfile and Pods folder.

  1. Complete Podfile according to your needs:
platform :ios, '13.0'
# this indicates the source where Cocoapods would find the pod to install
source 'https://gitlab.com/trustchile/movil-libs/lat_trust_mobile_ios_sso_library_podspec'
target 'AppName': do
use_frameworks!
...
# pod name and version to install
pod 'TrustSSO', '~> 1.5.8'
...
end
  1. Finally install previously specified dependencies using:
pod install

Associated Domains#

In order to support FIDO2 features, host application needs to in support Associated Domains for sharing web credentials.

image

The following JSON code represents the contents of a simple association file. ie. https://< fully qualified domain >/.well-known/apple-app-site-association

{
"webcredentials": {
"apps": [
"ABCDE12345.com.example.app"
]
},
}

The above string is composed by the Apple developer TeamID (ABCDE12345) followed by the ApplicationBundleID (com.example.app).


Initialize#

Use set(currentEnvironment: Environment) method to set the library's current environment (.prod or .test)

TrustSSOConfig.set(currentEnvironment: .test)
TrustSSOConfig.set(currentEnvironment: .prod)

Trust Transaction#

Methods#

Use shared instance to access TrustTransaction public methods. For example: Update an existing transaction receiving it's UUID as parameter

  • active: Bool value to be set on the respective transaction
  • completed: Bool value to be set on the respective transaction
  • authorizationMethod: String value that describes the auth method to be used
  • result: ResultHandler for success of failure cases
TrustTransaction.shared.updateTransaction(
transactionUuid: "12345",
authorizationMethod: "sms",
complete: true,
active: false,
) {
switch $0 {
case .success(let transaction):
// Do something with resulting transaction
case .failure(let error):
// Do something with resulting error
}
}

Fetch exsiting transactions for a specific user

  • userId: String value used for search transactions
  • result: ResultHandler for success of failure cases
TrustTransaction.shared.fetchTransactionsByUser(userId: "7304") {
switch $0 {
case .success(let transactions):
// Do something with resulting transaction
case .failure(let error):
// Do something with resulting error
}
}

Fetch exsiting transactions for a specific company

  • companyId: String value used for search transactions
  • result: closure that handles success of failure cases
TrustTransaction.shared.fetchTransactionsByCompany(companyId: "9512") {
switch $0 {
case .success(let transactions):
// Do something with resulting transactions array
case .failure(let error):
// Do something with resulting error
}
}

Trust Validation#

Methods#

Validate code using transactionUuid and otp value

  • transactionUuid: String needed for locating specific transaction
  • otp: Int value representing otp Int
  • result: ResultHandler for success of failure cases
TrustValidation.shared.validateCode(transactionUuid: "142", otp: 1) {
switch $0 {
case .success(let transaction):
// Do something with resulting transaction
case .failure(let error):
// Do something with resulting error
}
}

Validate QR code

  • code: String value representing code to validate
  • userId: String value representing user id
TrustValidation.shared.validateQrCode(code: "142", userId: "1") {
switch $0 {
case .success(let transaction):
// Do something with resulting transaction
case .failure(let error):
// Do something with resulting error
}
}

Trust FIDO2#

Use set(authenticationAnchor: UIWindow) method for configuring the view where the authentication request will be displayed.

TrustFIDO2.shared.set(authenticationAnchor: window)

Methods#

Register new user credentials

  • companyId: String valkue representing companyId
  • userId: String representing userId
TrustFIDO2.shared.registerRequest(userId: "7304", companyId: "9512") {
switch $0 {
case .success(let registerResultData):
// Do something with resulting data object
case .failure(let error):
// Do something with resulting error
}
}

Authenticate user credentials

  • userId: String value representing userId value
  • companyId: String value representing companyId value
TrustFIDO2.shared.signInRequest(userId: "7304", companyId: "9512") {
switch $0 {
case .success(let verificationResultData):
// Do something with resulting data object
case .failure(let error):
// Do something with resulting error
}
}

Trust IDP#

Methods#

Request authorization from client application user presenting a login form and then calling back to the client application

let trustIDP = TrustIDP.builder
.scheme("https://")
.baseURL("api.example.com")
.authPath("/example/path")
.scopes("example_scope")
.state("123456")
.resopnseType("example_type")
.acrValues("example_values")
.redirectURI("com.example.bundle//main")
.clientId("example_client_id")
.clientSecret("example_client_secret")
.grantType("authorization_code")
.build()
trustIDP?.requestAuthorization()

Ask for an AccessToken using a code provided in RequestAuthorization method

  • code: String value stored in application used to get AccessToken
  • result: ResultHandler for success of failure cases
TrustIDP.shared.tokenExchange(using: "idoj290pl21")

Trust Native#

Allows to obtain a login and a validation through an otp to obtain an access token through PKCE

Builder#

NameDescriptionDefault ValueOptional
scopesSpecifies the scopes-No
clientIDSet the client id-No
clientSecretSet the cliend secret-No
redirectUriSet the register redirect URI-Yes
responseTypeSpecifies the response type-Yes
grantTypeSpecifies the grand type-No
buildReturn a instance of TrustNative-No

Code example#

let trustNative = TrustNative.builder
.clientSecret(<YOUR_CLIENT_SECRET>)
.scope(<YOUR_SCOPES>)
.clientId(<YOUR_CLIENT_ID>)
.build()

Methods#

PerformLogin#

trustNative.performLogin() {
switch $0 {
case .success(let formResponse):
// Do something with resulting form response
case .failure(let error):
// Do something with resulting error
}
}

Description#

It returns a login type form if it is the first time it is instantiated, otherwise it will return a code form.

view_type.login_form: Means that the form that has been returned is of type login, the data of this form must be sent in the following steps view_type.code_form: Means that the form that has been returned is of type code, the data of this form must be sent in the following steps, the codes are obtained by sms, whatsapp and mail.

Login form example#
{
"data": {
"view_type": "login_form",
"fields": [
{
"name": "email",
"type": "mail"
},
{
"name": "password",
"type": "password"
}
]
}
}
Code form example#
{
"data": {
"view_type": "code_form",
"fields": [
{
"name": "a2f",
"type": "number"
}
]
}
}

Send Form login#

trustNative.sendForm(email: "example@email.com", password: "examplepassword") {
switch $0 {
case .success(let formStepResponse):
// Do something with resulting form step object
case .failure(let error):
// Do something with resulting error
}
}

Description#

next_step: true => Means that there is still one form to complete. next_step: false => Means that there are no more forms left to complete. token_available: false => Means can't get token token_available: true => Means token can be obtained

Form step true#

{
"data": {
"next_step": true,
"token_available": false
}
}

Form step false#

{
"data": {
"next_step": false,
"token_available": true
}
}

Send Form code#

trustNative.sendForm(a2f: "2k43") {
switch $0 {
case .success(let formStepResponse):
// Do something with resulting form step object
case .failure(let error):
// Do something with resulting error
}
}

Description#

next_step: true => Means that there is still one form to complete. next_step: false => Means that there are no more forms left to complete. token_available: false => Means can't get token token_available: true => Means token can be obtained

Form step true#

{
"data": {
"next_step": true,
"token_available": false
}
}

Form step false#

{
"data": {
"next_step": false,
"token_available": true
}
}

Get Token#

trustNative.getAccessToken() {
switch $0 {
case .success(let accessToken):
// Do something with resulting access token
case .failure(let error):
// Do something with resulting error
}
}

Description#

id_token: It is a jwt with the user information

{
"access_token": "dJflShMZsv1AYhttHPwUBI",
"refresh_token": null,
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzozODYwN",
"token_type": "Bearer",
"expires_in": 3600
}

Errors#

TrustError definition:

  • code: String value code of error check specification
  • localizedDescription: Error description as String

Codes#

Possible errors that can be found when integrating the SDK | Code | Value | |---|---| | 0 | Unknow error | | 400 | Bad request | | 401 | The request was unauthorized | | 403 | The request was forbidden | | 404 | The requested could not be found | | 405 | Method not allowed | | 500 | Internal server error | | 501 | Not implemented | | 502 | Bad gateway | | 503 | Service unavailable | | 1000 | Null or empty data | | 1001 | Null response body from server | | 1002 | Unexpected parameter or value | | 1003 | Error network connection | | 1004 | Error intent | | 1005 | Error response from fingerprint |

Last updated on by fcaro@trust.lat