{"id":22808909,"url":"https://github.com/okta/okta-mobile-swift","last_synced_at":"2025-04-07T07:14:41.621Z","repository":{"id":37082247,"uuid":"430841418","full_name":"okta/okta-mobile-swift","owner":"okta","description":"okta-mobile-swift","archived":false,"fork":false,"pushed_at":"2024-12-14T01:13:45.000Z","size":20769,"stargazers_count":47,"open_issues_count":11,"forks_count":19,"subscribers_count":85,"default_branch":"master","last_synced_at":"2024-12-28T02:04:04.096Z","etag":null,"topics":["authentication","ios","jwt","macos","oauth","oidc","okta","openid-connect","tvos","watchos"],"latest_commit_sha":null,"homepage":"https://github.com/okta/okta-mobile-swift","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/okta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-22T19:37:09.000Z","updated_at":"2024-12-26T04:26:06.000Z","dependencies_parsed_at":"2024-02-28T23:29:39.497Z","dependency_job_id":"ebe85099-c5ca-4926-9741-8e1d7a26b724","html_url":"https://github.com/okta/okta-mobile-swift","commit_stats":{"total_commits":237,"total_committers":11,"mean_commits":"21.545454545454547","dds":"0.14345991561181437","last_synced_commit":"3ca3e3b549d587c19c16349d9ac02a6871baa85a"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okta%2Fokta-mobile-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okta%2Fokta-mobile-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okta%2Fokta-mobile-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/okta%2Fokta-mobile-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/okta","download_url":"https://codeload.github.com/okta/okta-mobile-swift/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608153,"owners_count":20965952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","ios","jwt","macos","oauth","oidc","okta","openid-connect","tvos","watchos"],"created_at":"2024-12-12T11:12:46.364Z","updated_at":"2025-04-07T07:14:41.590Z","avatar_url":"https://github.com/okta.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[\u003cimg src=\"https://www.okta.com/sites/default/files/Dev_Logo-01_Large-thumbnail.png\" align=\"right\" width=\"256px\"/\u003e](https://devforum.okta.com/)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Support](https://img.shields.io/badge/support-Developer%20Forum-blue.svg)][devforum]\n[![API Reference](https://img.shields.io/badge/docs-reference-lightgrey.svg)][swiftdocs]\n\n\n# Okta Mobile SDK for Swift\n\nThe Okta Mobile SDK replaces our legacy mobile SDKs (such as okta-oidc-ios) and enables:\n\n* Streamlined development\n* Increased maintainability of the Okta portion of your code\n* Easier feature expansion\n* Support for use cases that were previously difficult or impractical to implement.\n\nThis new SDK is built as a platform, enabling you to choose the components you need for your app.\n\n**Table of Contents**\n\n\u003c!-- TOC depthFrom:2 depthTo:3 --\u003e\n\u003c!-- /TOC --\u003e\n\n## Release status\n\nThis library uses semantic versioning and follows Okta's [Library Version Policy][okta-library-versioning].\n\n| Version | Status                             |\n| ------- | ---------------------------------- |\n| 1.8.2   | ✔️ Stable                             |\n\nThe latest release can always be found on the [releases page][github-releases].\n\n## Need help?\n\nIf you run into problems using the SDK, you can:\n\n* Review the API documentation for [AuthFoundation][authfoundation-docs], [OktaOAuth2][oktaoauth2-docs], and [WebAuthenticationUI][webauthenticationui-docs]\n* Ask questions on the [Okta Developer Forums][devforum]\n* Post [issues][github-issues] here on GitHub (for code errors)\n\n## SDK Architecture\n\nThis SDK consists of several different libraries, each with detailed documentation.\n\n```mermaid\n  graph TD;\n    AuthFoundation--\u003eOktaOAuth2;\n    OktaOAuth2--\u003eWebAuthenticationUI;\n```\n\n- [AuthFoundation][authfoundation-docs] -- Common classes for managing credentials and used as a foundation for other libraries.\n- [OktaDirectAuth][oktadirectauth-docs] -- Direct Authentication capabilities for advanced browserless authentication (EA).\n- [OktaOAuth2][oktaoauth2-docs] -- OAuth2 authentication capabilities for advanced use-cases.\n- [WebAuthenticationUI][webauthenticationui-docs] -- Authenticate users using web-based OIDC flows.\n\nThis SDK enables you to build or support a myriad of different authentication flows and approaches.\n\n## Development Roadmap\n\nThis SDK is being actively developed, with plans for future expansion. At this time, we are seeking feedback from the developer community to evaluate:\n\n* The overall SDK and its components\n* The APIs and overall developer experience\n* Use-cases or features that may be missed or do not align with your application’s needs\n* Suggestions for future development\n* Any other comments or feedback on this new direction.\n\n### Key Features\n\nSeveral key features and capabilities are introduced with this library, with some notable improvements listed below.\n\n| Feature |\n| ------- |\n| Simple OIDC web-based sign in |\n| Credential management (secure storage, retrieval, etc) |\n| Multi-token handling (store and use tokens for multiple users, scopes, etc) |\n| Authorization Code Flow |\n| Native SSO / Token Exchange Flow |\n| Device Authorization Grant Flow |\n| Resource Owner Flow |\n| Simplified JWT parsing and handling |\n| Streamlined authorization of URLSession requests using credential tokens |\n| Many extension points for customizability, monitoring, and tracking |\n\n## Getting Started\n\nTo get started, you will need:\n\n* An Okta account, called an _organization_ (sign up for a free [developer organization](https://developer.okta.com/signup) if you need one).\n* An Okta Application configured as a \"Native App\". Use Okta's administrator console to create the application by following the wizard and using default properties.\n* Xcode 13.x, targeting one of the supported platforms and target versions (see the [Support Policy][support-policy] below).\n\nFor examples of how this SDK can be utilized, please refer to the [sample applications](Samples) included within this repository.\n\n## Install\n\n### Swift Package Manager\n\nAdd the following to the `dependencies` attribute defined in your `Package.swift` file. You can select the version using the `majorVersion` and `minor` parameters. For example:\n\n```swift\ndependencies: [\n    .Package(url: \"https://github.com/okta/okta-mobile-swift.git\", majorVersion: \u003cmajorVersion\u003e, minor: \u003cminor\u003e)\n]\n```\n\n### CocoaPods\n\nSimply add the following line to your `Podfile`:\n\n```ruby\npod 'OktaWebAuthenticationUI'\n```\n\nThen install it into your project:\n\n```bash\npod install --repo-update\n```\n\nIf you are interested in only consuming the OktaOAuth2 library, instead use the following:\n\n```ruby\npod 'OktaOAuth2'\n```\n\nIf you are participating in the Early Access preview of the Okta Direct Authentication API, use the following:\n\n```ruby\npod 'OktaDirectAuth'\n```\n\n## Usage Guide\n\n### Web Authentication using OIDC\n\nThe simplest way to integrate authentication in your app is with OIDC through a web browser, using the Authorization Code Flow grant.\n\n#### Configure your OIDC Settings\n\nBefore authenticating your user, you need to create your client configuration using the settings defined in your application in the Okta Developer Console. The simplest approach is to use a `Okta.plist` configuration file to specify these settings. Ensure one is created with the following fields:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003c!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"\u003e\n\u003cplist version=\"1.0\"\u003e\n  \u003cdict\u003e\n    \u003ckey\u003eissuer\u003c/key\u003e\n    \u003cstring\u003ehttps://{yourOktaDomain}.com\u003c/string\u003e\n    \u003ckey\u003eclientId\u003c/key\u003e\n    \u003cstring\u003e{clientId}\u003c/string\u003e\n    \u003ckey\u003eredirectUri\u003c/key\u003e\n    \u003cstring\u003e{redirectUri}\u003c/string\u003e\n    \u003ckey\u003elogoutRedirectUri\u003c/key\u003e\n    \u003cstring\u003e{logoutRedirectUri}\u003c/string\u003e\n    \u003ckey\u003escopes\u003c/key\u003e\n    \u003cstring\u003eopenid profile offline_access\u003c/string\u003e\n  \u003c/dict\u003e\n\u003c/plist\u003e\n```\n\nAlternatively, you can supply those values to the constructor the `WebAuthentication` we're about to discuss in the next section.\n\n#### Create a Web Authentication session\n\nOnce you've configured your application settings within your `Okta.plist` file, a shared configuration is automatically available through the `WebAuthentication.shared` singleton property. With that in place, you can use the convenience `WebAuthentication.signIn(from:)` method to prompt the user to sign in.\n\n```swift\nimport WebAuthenticationUI\n\nfunc signIn() async {\n    let token = try await WebAuthentication.signIn(from: view.window)\n    let credential = try Credential.store(token)\n}\n```\n\nThe `signIn(from:)` function returns a token and, by using the `Credential` class, you can save the token and use it within your application.\n\n### Authentication using Device Code-Flow Grant\n\nFor headless devices, or devices that are difficult to use a keyboard (e.g. AppleTV), your application can use OktaOAuth2 directly with the `DeviceAuthorizationFlow` class. This will enable you to present a easy to remember code to your user, which they can use on a different device to authorize your application.\n\nUsing this is simple:\n\n1. Create an instance of `DeviceAuthorizationFlow`\n\n```swift\nlet flow = DeviceAuthorizationFlow(\n    issuer: URL(string: \"https://example.okta.com\")!,\n    clientId: \"abc123client\",\n    scopes: \"openid offline_access email profile\")\n```\n\n2. Start an authentication session to receive the code and authorize URL to present to your user.\n\n```swift\nlet context = try await flow.start()\nlet code = context.userCode\nlet uri = context.verificationUri\n```\n\n3. Wait for the user to authorize the application from another device.\n\n```swift\nlet token = try await flow.resume(with: context)\n```\n\n### Authentication using Native SSO flow\n\nWhen using the `device_sso` scope, your application can receive a \"device secret\", which can be used in combination with your user's ID token to exchange new credentials. To use this within your application, you would use the `TokenExchangeFlow` to exchange those sets of tokens.\n\n```swift\nlet flow = TokenExchangeFlow(\n    issuer: URL(string: \"https://example.okta.com\")!,\n    clientId: \"abc123client\",\n    scopes: \"openid offline_access email profile\",\n    audience: .default)\n\nlet token = try await flow.start(with: [\n    .actor(type: .deviceSecret, value: \"DeviceToken\"),\n    .subject(type: .idToken, value: \"IDToken\")\n])\n```\n\n### Authentication with Username/Password\n\nFor simple authentication use-cases, you can use the `ResourceOwnerFlow` class to authenticate with a plain username and password.\n\n\u003e *NOTE:* The ResourceOwnerFlow class has been marked as deprecated, since its functionality is being replaced with the more comprehensive OktaDirectAuth library.\n\n```swift\nlet flow = ResourceOwnerFlow(issuer: URL(string: \"https://example.okta.com\")!,\n                             clientId: \"abc123client\",\n                             scopes: \"openid offline_access email profile\")\nlet token = try await flow.start(username: \"jane.doe\", password: \"secretPassword\")\n```\n\n### Authentication using Direct Authentication (EA)\n\nFor simple authentication use-cases, you can use the `ResourceOwnerFlow` class to authenticate with a plain username and password.\n\n\u003e **NOTE:** The Okta Direct Authentication API is currently marked as Early Access (EA) and is not generally available yet.\n\n```swift\nlet flow = DirectAuthenticationFlow(issuer: URL(string: \"https://example.okta.com\")!,\n                                    clientId: \"abc123client\",\n                                    scopes: \"openid offline_access email profile\")\nswitch try await flow.start(\"jane.doe@example.com\", with: .password(\"secretPassword\")) {\n    case .success(let token):\n        // Store the token\n    case .mfaRequired(_):\n        // Continue authentication\n}\n```\n\nFor more information, see the [OktaDirectAuth API documentation][oktadirectauth-docs].\n\n## Storing and using tokens\n\nOnce your user has authenticated and you have a `Token` object, your application can store and use those credentials. The most direct approach is to use the `Credential.store(_:tags:security:)` function.\n\n```swift\nlet credential = try Credential.store(token)\n```\n\nAs a convenience, the SDK provides a `default` static property on the `Credential` class. This provides a simple way to identify if a user is currently authenticated, and to quickly access that user's credentials. When storing a new credential, if one isn't already stored, it will automatically be assigned as the default.\n\n```swift\nif let credential = Credential.default {\n    // The user is signed in. Start by refreshing it.\n    try await credential.refreshIfNeeded()\n}\n```\n\n### Finding credentials by their unique identifier\n\nWhen a token is stored, it is assigned a unique ID, which can be used to differentiate between tokens and to retrieve a token at a later date.\n\n```swift\nlet tokenId = token.id\n\n// Later, retrieve the token\nif let credential = try Credential.with(id: tokenId) {\n    // Use the credential\n}\n```\n\n### Assigning and finding credentials using custom tags\n\nFor more complex applications, you may need to manage multiple credentials (e.g. multi-user sign-in, different tokens for app extensions, granular scopes for different portions of your application, etc). To make it easier to differentiate between credentials, you can assign tags to them which can later be used to identify them.\n\n```swift\ntry Credential.store(token, tags: [\"customTag\": \"someValue\"])\n```\n\nThe credential can later be retrieved based on these tags.\n\n```swift\nif let credential = try Credential.find(where: { $0.tags[\"customTag\"] == \"someValue\" }).first {\n    // Use the credential\n}\n```\n\nA credential's tags are available through its `tags` property, and can be changed after the fact.\n\n```\nif !credential.tags.contains(\"someCustomTag\") {\n    credential.tags[\"someCustomTag\"] = \"someValue\"\n}\n\n// Or use the following method to intercept exceptions\ntry credential.setTags([\"customTag\": \"someValue\"])\n```\n\n### Finding credentials using ID token claims\n\nThis SDK simplifies access to JWT tokens and their claims. In fact, a Token's `idToken` property is automatically exposed as an instance of `JWT`. Using this, you can enumerate and retrieve credentials based on the claims associated with their tokens.\n\n```swift\nif let credential = try Credential.find(where: { $0.email == \"user@example.com\" }).first {\n    // Use the credential\n}\n```\n\n### Rate Limit Handling\n\nThe Okta API will return 429 responses if too many requests are made within a given time. Please see [Rate Limiting at Okta](https://developer.okta.com/docs/api/getting_started/rate-limits) for a complete\nlist of which endpoints are rate limited. This SDK automatically retries requests on 429 errors. The default configuration is as follows:\n\n| Configuration Option | Description |\n| ---------------------- | -------------- |\n| maximumCount         | The number of times to retry. The default value is `3`. |\n\n#### Customizing Rate Limit \n\nTo customize how rate limit is handled, conform to the `APIClientDelegate` protocol, implement the `shouldRetry(request:rateLimit:)` method, and add your class as a delegate for the appropriate client. When any request sent through that client receives an HTTP 429 error response, it will allow you to customize the rate limit behavior.\n\n```swift\nimport AuthFoundation\n\nfunc login() {\n    // Configure your authentication flow, before running the following command\n    flow.client.add(delegate: self)\n}\n\nextension OAuth2Client {\n    public func api(client: APIClient, shouldRetry request: URLRequest) -\u003e APIRetry {\n        return .doNotRetry\n    }\n}\n```\n\nFor more information, refer to the API documentation for the `APIRetry` enumeration.\n\n## Migration from legacy SDKs\n\nThis collection of SDKs intend to replace the following SDKs:\n\n* [okta-oidc-ios](https://github.com/okta/okta-oidc-ios)\n* [okta-ios-jwt](https://github.com/okta/okta-ios-jwt)\n* [okta-storage-swift](https://github.com/okta/okta-storage-swift)\n\nIf your application currently uses OktaOidc, facilities are in place to migrate your existing users to the new SDK. For more information, see the `SDKVersion.Migration` class for details.\n\n## Running the Samples\n\nSeveral applications are available to demonstrate different workflows of this SDK. For more information, please see the [sample applications](Samples).\n\n## Support Policy\n\nThis policy defines the extent of the support for Xcode, Swift, and platform (iOS, macOS, tvOS, and watchOS) versions.\n\n### Xcode\n\nThe only supported versions of Xcode are those that can be currently used to submit apps to the App Store. Once a Xcode version becomes unsupported, dropping support for it will not be considered a breaking change, and will be done in a minor release.\n\n### Swift\n\nThe minimum supported Swift 5 minor version is the one released with the oldest-supported Xcode version. Once a Swift 5 minor becomes unsupported, dropping support for it will not be considered a breaking change, and will be done in a minor release.\n\n### Platforms\n\nOnly the last 4 major platform versions are officially supported, unless there are platform limitations that limit our ability to support older versions.\n\n| Platform    | Supported | Best-Effort |\n| ----------- | --------- | ----------- |\n| iOS         | 13.0      | 12.0        |\n| tvOS        | 13.0      | 12.0        |\n| watchOS     | 7.0       | 7.0         |\n| visionOS    | 1.0       | 1.0         |\n| macCatalyst | 13.0      | 13.0        |\n| macOS       | 12.0      | 10.15       |\n\nOnce a platform version becomes unsupported, dropping support for it will not be considered a breaking change and will be done in a minor release. For example, iOS 13 will cease to be supported when iOS 18 gets released, and might be dropped in a minor release.\n\nIn the case of macOS, the yearly named releases are considered a major platform version for this Policy, regardless of the actual version numbers.\n\n\u003e *Note:* Older OS versions are supported in a best-effort manner. Unless there are API limitations that prevent the SDK from working effectively on older OS versions, the minimum requirements will not be changed.\n\u003e \n\u003e Additionally, Linux compatibility is considered best-effort and is not officially supported.\n\n### Legacy SDK support\n\nAfter the okta-mobile-swift SDK becomes generally available, we intend all new feature development to proceed within this new library. We plan to support okta-oidc-ios (and our other legacy SDKs that okta-mobile-swift replaces) with critical bug and security fixes for the foreseeable future. \n\n## Development\n\n### Protecting Test Configuration\n\nThis repository contains two files within `Samples/Shared` which are used to expose test credentials to automated tests as well as the sample applications.\n\n* [Okta.plist](Samples/Shared/Okta.plist)\n* [TestConfiguration.xcconfig](Samples/Shared/TestConfiguration.xcconfig)\n\nTo protect against accidental changes being introduced to these files, it is recommended that you use the following command after cloning this repository:\n\n```bash\ngit config core.hooksPath ./.githooks\n```\n\nThis will run checks before committing changes to ensure these files are not altered.\n\n### Running Tests\n\nTests can be run on macOS from the command-line using:\n\n```bash\nswift test\n```\n\nAlternatively, if you wish to run tests within Linux, you can utilize Docker from a macOS environment to run Linux tests:\n\n```bash\ndocker run --rm --privileged --interactive --tty \\\n    --volume \"$(pwd):/src\" --workdir \"/src\" swift:latest \\\n    swift test\n```\n\n## Known issues\n\n## Contributing\n\nWe are happy to accept contributions and PRs! Please see the [contribution guide](CONTRIBUTING.md) to understand how to structure a contribution.\n\n[devforum]: https://devforum.okta.com/\n[swiftdocs]: https://developer.okta.com/okta-mobile-swift/latest/\n[lang-landing]: https://developer.okta.com/code/swift/\n[github-issues]: https://github.com/okta/okta-mobile-swift/issues\n[github-releases]: https://github.com/okta/okta-mobile-swift/releases\n[authfoundation-docs]: https://okta.github.io/okta-mobile-swift/development/authfoundation/\n[oktadirectauth-docs]: https://okta.github.io/okta-mobile-swift/development/oktadirectauth/\n[oktaoauth2-docs]: https://okta.github.io/okta-mobile-swift/development/oktaoauth2/\n[webauthenticationui-docs]: https://okta.github.io/okta-mobile-swift/development/webauthenticationui/\n[Rate Limiting at Okta]: https://developer.okta.com/docs/api/getting_started/rate-limits\n[okta-library-versioning]: https://developer.okta.com/code/library-versions\n[support-policy]: #support-policy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokta%2Fokta-mobile-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fokta%2Fokta-mobile-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fokta%2Fokta-mobile-swift/lists"}