Swiftpack.co - Package - auth0/Auth0.swift

Auth0.swift

CircleCI Coverage Status Version License Platform Swift 5.3

Swift toolkit that lets you communicate efficiently with many of the Auth0 API functions and enables you to seamlessly integrate the Auth0 login.

Important Notices

Behaviour changes in iOS 13 related to Web Authentication require that developers using Xcode 11 with this library must compile using Swift 5.x. This should be the default setting applied when updating, unless it has been manually set. However, we recommend checking that this value is set correctly.

Table of Contents

Requirements

  • iOS 9+ / macOS 10.11+ / tvOS 9.0+ / watchOS 2.0+
  • Xcode 11.4+ / 12.x
  • Swift 4.x / 5.x

Installation

Cocoapods

If you are using Cocoapods, add this line to your Podfile:

pod 'Auth0', '~> 1.30'

Then run pod install.

For more information on Cocoapods, check their official documentation.

Carthage

If you are using Carthage, add the following line to your Cartfile:

github "auth0/Auth0.swift" ~> 1.30

Then run carthage bootstrap.

For more information about Carthage usage, check their official documentation.

SPM

If you are using the Swift Package Manager, open the following menu item in Xcode:

File > Swift Packages > Add Package Dependency...

In the Choose Package Repository prompt add this url:

https://github.com/auth0/Auth0.swift.git

Then press Next and complete the remaining steps.

For further reference on SPM, check its official documentation.

Getting Started

Authentication with Universal Login (iOS / macOS 10.15+)

  1. Import Auth0 into your project.
import Auth0
  1. Present the Universal Login page.
Auth0
    .webAuth()
    .audience("https://{YOUR_AUTH0_DOMAIN}/userinfo")
    .start { result in
        switch result {
        case .success(let credentials):
            print("Obtained credentials: \(credentials)")
        case .failure(let error):
            print("Failed with \(error)")
        }
    }

This snippet sets the audience to ensure OIDC compliant responses, this can also be achieved by enabling the OIDC Conformant switch in your Auth0 dashboard under Application / Settings / Advanced / OAuth.

  1. Allow Auth0 to handle authentication callbacks. In your AppDelegate.swift, add the following:

iOS

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any]) -> Bool {
    return Auth0.resumeAuth(url)
}

macOS

func application(_ application: NSApplication, open urls: [URL]) {
    Auth0.resumeAuth(urls)
}

Configuration

In order to use Auth0 you need to provide your Auth0 ClientId and Domain.

Auth0 ClientId & Domain can be found in your Auth0 Dashboard.

Adding Auth0 Credentials

In your application bundle add a plist file named Auth0.plist with the following information:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>ClientId</key>
  <string>YOUR_AUTH0_CLIENT_ID</string>
  <key>Domain</key>
  <string>YOUR_AUTH0_DOMAIN</string>
</dict>
</plist>

As an alternative, you can pass the ClientId & Domain programmatically.

// When using Universal Login
Auth0.webAuth(clientId: "{YOUR_AUTH0_CLIENT_ID}", domain: "{YOUR_AUTH0_DOMAIN}")

// When using the Authentication API
Auth0.authentication(clientId: "{YOUR_AUTH0_CLIENT_ID}", domain: "{YOUR_AUTH0_DOMAIN}")

Configure Callback URLs (iOS / macOS)

Callback URLs are the URLs that Auth0 invokes after the authentication process. Auth0 routes your application back to this URL and appends additional parameters to it, including a token. Since callback URLs can be manipulated, you will need to add your callback URL to the Allowed Callback URLs field in the Auth0 Dashboard. This will enable Auth0 to recognize these URLs as valid. If omitted, authentication will not be successful.

In your application's Info.plist file, register your iOS / macOS Bundle Identifer as a custom scheme.

<!-- Info.plist -->

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>None</string>
        <key>CFBundleURLName</key>
        <string>auth0</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>YOUR_BUNDLE_IDENTIFIER</string>
        </array>
    </dict>
</array>

If your Info.plist is not shown in this format, you can Right Click on Info.plist in Xcode and then select Open As / Source Code.

Finally, go to your Auth0 Dashboard and make sure that your application's Allowed Callback URLs field contains the following entry:

YOUR_BUNDLE_IDENTIFIER://YOUR_AUTH0_DOMAIN/ios/YOUR_BUNDLE_IDENTIFIER/callback

e.g. If your bundle identifier was com.company.myapp and your Auth0 domain was company.auth0.com, then this value would be:

com.company.myapp://company.auth0.com/ios/com.company.myapp/callback

Next Steps

Learning Resources

Check out the iOS Swift QuickStart Guide to find out more about the Auth0.swift toolkit and explore our tutorials and sample projects.

Common Tasks

Retrieve user information

Auth0
   .authentication()
   .userInfo(withAccessToken: accessToken)
   .start { result in
       switch result {
       case .success(let profile):
           print("User Profile: \(profile)")
       case .failure(let error):
           print("Failed with \(error)")
       }
   }

Renew user credentials

Use a Refresh Token to renew user credentials. It's recommended that you read and understand the refresh token process before implementing.

Auth0
    .authentication()
    .renew(withRefreshToken: refreshToken)
    .start { result in
        switch result {
        case .success(let credentials):
            print("Obtained new credentials: \(credentials)")
        case .failure(let error):
            print("Failed with \(error)")
        }
    }

Disable Single Sign On (iOS 13+ / macOS)

Add the useEphemeralSession() method to the chain to disable SSO on iOS 13+ and macOS. This way the system will not display the consent popup that otherwise shows up when SSO is enabled. It has no effect on older versions of iOS.

Auth0
    .webAuth()
    .audience("https://{YOUR_AUTH0_DOMAIN}/userinfo")
    .useEphemeralSession()
    .start { result in
        switch result {
        case .success(let credentials):
            print("Obtained credentials: \(credentials)")
        case .failure(let error):
            print("Failed with \(error)")
        }
    }

Credentials Management Utility

The credentials manager utility provides a convenience to securely store and retrieve the user's credentials from the Keychain.

let credentialsManager = CredentialsManager(authentication: Auth0.authentication())

Store Credentials

Store user credentials securely in the Keychain.

credentialsManager.store(credentials: credentials)

Retrieve stored credentials

Credentials will automatically be renewed (if expired) using the refresh token. The scope offline_access is required to ensure the refresh token is returned.

This method is not thread-safe, so if you're using Refresh Token Rotation you should avoid calling this method concurrently (might result in more than one renew request being fired, and only the first one will succeed).

credentialsManager.credentials { error, credentials in
    guard error == nil, let credentials = credentials else { 
        return print("Failed with \(error)") 
    }
    print("Obtained credentials: \(credentials)")
}

Clearing credentials and revoking refresh tokens

Credentials can be cleared by using the clear function, which clears credentials from the Keychain.

let didClear = credentialsManager.clear()

In addition, credentials can be cleared and the refresh token revoked using a single call to revoke. This function will attempt to revoke the current refresh token stored by the credential manager and then clear credentials from the Keychain. If revoking the token results in an error, then the credentials are not cleared:

credentialsManager.revoke { error in
    guard error == nil else {
        return print("Failed to revoke refresh token: \(error)")
    }
    
    print("Success")
}

Biometric authentication

You can enable an additional level of user authentication before retrieving credentials using the biometric authentication supported by your device e.g. Face ID or Touch ID.

credentialsManager.enableBiometrics(withTitle: "Touch to Login")

Native Social Login

Sign in With Apple

If you've added the Sign In with Apple flow to your app, you can use the string value from the authorizationCode property obtained after a successful Apple authentication to perform a token exchange for Auth0 tokens.

Auth0
    .authentication()
    .login(appleAuthorizationCode: authCode)
    .start { result in
        switch result {
        case .success(let credentials):
            print("Obtained credentials: \(credentials)")
        case .failure(let error):
            print("Failed with \(error)")
        }
}

Find out more about Setting up Sign in with Apple with Auth0.

Facebook Login

If you've added the Facebook Login flow to your app, after a successful Faceboook authentication you can request a Session Access Token and the Facebook user profile, and use them to perform a token exchange for Auth0 tokens.

Auth0
    .authentication()
    .login(facebookSessionAccessToken: sessionAccessToken, profile: profile)
    .start { result in
        switch result {
        case .success(let credentials):
            print("Obtained credentials: \(credentials)")
        case .failure(let error):
            print("Failed with \(error)")
        }
}

Find out more about Setting up Facebook Login with Auth0.

Authentication API (iOS / macOS / tvOS)

The Authentication API exposes AuthN/AuthZ functionality of Auth0, as well as the supported identity protocols like OpenID Connect, OAuth 2.0, and SAML. We recommend using Universal Login but if you wish to build your own UI, you can use our API endpoints to do so. However, some Auth flows (grant types) are disabled by default so you must enable them via your Auth0 Dashboard as explained in Update Grant Types.

These are the required Grant Types that needs to be enabled in your application:

  • Password: For login with username/password using a realm (or connection name). If you set the grants via API you should activate both http://auth0.com/oauth/grant-type/password-realm and password, otherwise Auth0 Dashboard will take care of activating both when Password is enabled.

Login with database connection (via Realm)

Auth0
    .authentication()
    .login(usernameOrEmail: "support@auth0.com",
           password: "secret-password",
           realm: "Username-Password-Authentication",
           scope: "openid profile")
     .start { result in
         switch result {
         case .success(let credentials):
            print("Obtained credentials: \(credentials)")
         case .failure(let error):
            print("Failed with \(error)")
         }
     }

This requires Password Grant or http://auth0.com/oauth/grant-type/password-realm.

Sign up with database connection

Auth0
    .authentication()
    .createUser(email: "support@auth0.com",
                password: "secret-password",
                connection: "Username-Password-Authentication",
                userMetadata: ["first_name": "First", "last_name": "Last"])
    .start { result in
        switch result {
        case .success(let user):
            print("User Signed up: \(user)")
        case .failure(let error):
            print("Failed with \(error)")
        }
    }

Management API (Users)

You can request more information about a user's profile and manage the user's metadata by accessing the Auth0 Management API. For security reasons native mobile applications are restricted to a subset of User based functionality.

You can find a detailed guide in this iOS Swift QuickStart.

Link an account

Auth0
    .users(token: idToken)
    .link("user identifier", withOtherUserToken: "another user token")
    .start { result in
        switch result {
        case .success(let userInfo):
            print("User: \(userInfo)")
        case .failure(let error):
            print("Failed with \(error)")
        }
    }

Custom Domains

If you are using Custom Domains and need to call an Auth0 endpoint such as /userinfo, please use the Auth0 domain specified for your Application in the Auth0 Dashboard.

Example: .audience("https://{YOUR_AUTH0_DOMAIN}/userinfo")

Users of Auth0 Private Cloud with Custom Domains still on the legacy behavior need to specify a custom issuer to match the Auth0 domain before starting the authentication. Otherwise, the ID Token validation will fail.

Example: .issuer("https://{YOUR_AUTH0_DOMAIN}/")

Bot Detection

If you are using the Bot Detection feature and performing database login/signup via the Authentication API, you need to handle the isVerificationRequired error. It indicates that the request was flagged as suspicious and an additional verification step is necessary to log the user in. That verification step is web-based, so you need to use Universal Login to complete it.

let email = "support@auth0.com"
let realm = "Username-Password-Authentication"
let scope = "openid profile"

Auth0
    .authentication()
    .login(usernameOrEmail: email,
           password: "secret-password",
           realm: realm,
           scope: scope)
     .start { result in
         switch result {
         case .success(let credentials):
            print("Obtained credentials: \(credentials)")
         case .failure(let error as AuthenticationError) where error.isVerificationRequired:
            DispatchQueue.main.async {
                Auth0
                    .webAuth()
                    .connection(realm)
                    .scope(scope)
                    .parameters(["login_hint": email])
                    // ☝🏼 So the user doesn't have to type it again
                    .start { result in
                        // Handle result
                    }
            }
         case .failure(let error):
            print("Failed with \(error)")
         }
     }

In the case of signup, you can add an additional parameter to make the user land directly on the signup page.

.parameters(["login_hint": email, "screen_hint": "signup"])

Check out how to set up Universal Login in the Getting Started section.

You don't need to handle this error if you're using the deprecated login methods.

Logging

To enable Auth0.swift to log HTTP request and OAuth2 flow for debugging you can call the following method in either WebAuth, Authentication or Users object:

var auth0 = Auth0.authentication()
auth0.logging(enabled: true)

Then for a OAuth2 authentication you'll see something similar to the following:

Safari: https://samples.auth0.com/authorize?.....
URL: com.auth0.myapp://samples.auth0.com/ios/com.auth0.MyApp/callback?...
POST https://samples.auth0.com/oauth/token HTTP/1.1
Content-Type: application/json

{"code":"...","client_id":"...","grant_type":"authorization_code","redirect_uri":"com.auth0.MyApp:\/\/samples.auth0.com\/ios\/com.auth0.MyApp\/callback","code_verifier":"..."}

HTTP/1.1 200
Pragma: no-cache
Content-Type: application/json
Strict-Transport-Security: max-age=3600
Date: Thu, 09 Jun 2016 19:04:39 GMT
Content-Length: 57
Cache-Control: no-cache
Connection: keep-alive

{"access_token":"...","token_type":"Bearer"}

Set this flag only when DEBUGGING to avoid leaking user's credentials in the device log.

What is Auth0?

Auth0 helps you to:

  • Add authentication with multiple sources, either social identity providers such as Google, Facebook, Microsoft Account, LinkedIn, GitHub, Twitter, Box, Salesforce (amongst others), or enterprise identity systems like Windows Azure AD, Google Apps, Active Directory, ADFS, or any SAML Identity Provider.
  • Add authentication through more traditional username/password databases.
  • Add support for linking different user accounts with the same user.
  • Support for generating signed JSON Web Tokens to call your APIs and flow the user identity securely.
  • Analytics of how, when, and where users are logging in.
  • Pull data from other sources and add it to the user profile through JavaScript rules.

Create a Free Auth0 Account

  1. Go to Auth0 and click Sign Up.
  2. Use Google, GitHub, or Microsoft Account to login.

Issue Reporting

If you have found a bug or to request a feature, please raise an issue. Please do not report security vulnerabilities on the public GitHub issue tracker. The Responsible Disclosure Program details the procedure for disclosing security issues.

Author

Auth0

License

This project is licensed under the MIT license. See the LICENSE file for more info.

Github

link
Stars: 137

Used By

Total: 2

Releases

1.30.1 -

Fixed

1.30.0 -

Added

  • Added clearSession to the Objective-C WebAuth wrapper #426 (Widcket)
  • Added Swift Package Manager support [SDK-2014] #425 (Widcket)

1.29.0 -

⚠️ This release adds support for Xcode 12 and drops support for Xcode < 11.4

Changed

Fixed

  • Bugfix for minTTL on CredentialsManager.swift #420 (heyzooi)

1.28.0 -

Added

  • Added support for custom issuer for ID Token validation [SDK-1909] #411 (Widcket)
  • Added CredentialsManager to watchOS target [SDK-1906] #409 (Widcket)
  • Added isVerificationRequired error [SDK-1865] #408 (Widcket)

1.27.0 -

Added

  • Added TTL renewal of credentials in CredentialsManager [SDK-1818] #399 (Widcket)

1.26.0 -

Added

  • Added Sign In with Apple profile parameter #392 (ejensen)

Changed

  • Moved NativeAuth.start() into the NativeAuth protocol declaration #390 (ejensen)

1.25.0 -

Added

  • Added support for ephemeral sessions [SDK-1559] #388 (Widcket)
  • Bumped dependencies [SDK-1630] #386 (Widcket)

1.24.1 -

Fixed

  • Added compilation conditions to Podspec #384 (Widcket)

1.24.0 -

Added

  • Added WebAuth support to macOS [SDK-1545] #381 (Widcket)

1.23.0 -

Added

  • Added support for Refresh Token Rotation [SDK-1420] #369 (Widcket)
  • Added support for iOS extensions #365 (Widcket)
  • Added Facebook token exchange method [SDK-1401] #358 (Widcket)

Deprecated

Fixed

Security

1.22.1 -

Fixed

Fixed build failure with SimpleKeychain 0.11.0 #354 (jshier)

1.22.0 -

Added

  • Added redirect URL method to WebAuth builder [SDK-1299] #351 (Widcket)

Changed

  • Refactored SIWA token exchange method [SDK-1349] #350 (Widcket)

1.21.0 -

Added

Fixed

1.20.0 -

Added

1.19.3 -

Fixed

1.19.2 -

Added

  • Add support for extended profile using SIWA token exchange #322 (asmclean)

1.19.1 -

Added

  • Renew tokens in Credentials Manager if either token has expired [SDK-999] #319 (cocojoe)

Fixed

  • Fix non-main thread use during inspection in SafariViewController [SDK-1119] #318 (cocojoe)

1.19.0 -

Added

  • CredentialsManager function to clear and revoke the refresh token #312 (stevehobbsdev)

1.18.0 -

Added

  • Default DismissButtonStyle when using SFSafariViewController iOS 11+ #305 (andrewfoghel)
  • Added SIWA token exchange support #304 (cocojoe)

1.17.1 -

Fixed

  • Fixed ability to clear WebAuth session in iOS 13 #301 (matt)

1.17.0 -

Added

  • Added support for iOS13 changes in ASWebAuthenticationSession #297 (cocojoe)
  • Added authentication method for default directory login #296 (cocojoe)

Notes Behaviour changes in iOS 13 relating to Web Authentication require that in Xcode 11 this library must be compiled using Swift 5.x. This should be the default setting unless it has been manually changed.

1.16.1 -

Fixed

  • Fixed ObjMembers attribute added for ObjC access #289 (cocojoe)

1.16.0 -

Added

  • Added support for root attributes when creating a new user #287 (cocojoe)

Fixed

  • Fix: Remove force unwrap in AuthSession handler #286 (cocojoe)
  • Fix Dismiss AS/SF authentication sessions upon deep-link callback #281 (cysp)
  • Update app configuration error message for PKCE #280 (lbalmaceda)

1.15.0 -

Added

1.14.2 -

Changed

  • Ensure URL encoding of + as %2B Authorize URL [SDK-691] #259 (cocojoe)
  • Updated Auth0 Telemetry Format #256 (cocojoe)

1.14.1 -

Fixed

  • Add Fix for Brew in Swift 3.0 CI #254 (cocojoe)
  • Pods Fix - Move AuthenticationServices to weak_framework section #253 (ivabra)

1.14.0 -

Added

Fixed

  • Ensure correct thread execution in test app #227 (cocojoe)

1.13.0 -

Fixed

1.12.0 -

Added

  • Added support for custom Keychain key in Credentials Manager #208 (danielphillips)
  • Enable Credentials Manager for tvOS and Mac Platforms #206 (cocojoe)

Fixed

1.10.1 -

Fixed

  • Fixed client ID and redirect URL query items not being passed in nonfederated clearSession() #188 (Rypac)