{"id":811,"url":"https://github.com/p2/OAuth2","last_synced_at":"2025-08-06T14:31:11.319Z","repository":{"id":17739718,"uuid":"20580793","full_name":"p2/OAuth2","owner":"p2","description":"OAuth2 framework for macOS and iOS, written in Swift.","archived":false,"fork":false,"pushed_at":"2024-05-16T21:56:34.000Z","size":6587,"stargazers_count":1146,"open_issues_count":72,"forks_count":277,"subscribers_count":39,"default_branch":"main","last_synced_at":"2024-10-29T17:52:55.359Z","etag":null,"topics":["ios","macos","oauth2","oauth2-client","oauth2-flow","tvos"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/p2.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-06-06T23:12:32.000Z","updated_at":"2024-10-26T01:46:53.000Z","dependencies_parsed_at":"2024-06-18T12:32:13.847Z","dependency_job_id":"760d65d9-3eca-45e5-88b4-c826c7bb2060","html_url":"https://github.com/p2/OAuth2","commit_stats":{"total_commits":464,"total_committers":63,"mean_commits":7.365079365079365,"dds":0.2844827586206896,"last_synced_commit":"3f6a18beb221636581e66d8d0cbec1a3948b4df3"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p2%2FOAuth2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p2%2FOAuth2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p2%2FOAuth2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p2%2FOAuth2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/p2","download_url":"https://codeload.github.com/p2/OAuth2/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226940195,"owners_count":17706671,"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":["ios","macos","oauth2","oauth2-client","oauth2-flow","tvos"],"created_at":"2024-01-05T20:15:31.867Z","updated_at":"2024-12-09T14:31:11.697Z","avatar_url":"https://github.com/p2.png","language":"Swift","readme":"OAuth2\n======\n\n[![Build Status](https://travis-ci.org/p2/OAuth2.svg?branch=main)](https://travis-ci.org/p2/OAuth2)\n[![License](https://img.shields.io/:license-apache-blue.svg)](LICENSE.txt)\n\nOAuth2 frameworks for **macOS**, **iOS** and **tvOS** written in Swift 5.\n\n- [⤵️ Installation](#installation)\n- [🛠 Usage](#usage)\n- [🖥 Sample macOS app][sample] (with data loader examples)\n- [📖 Technical Documentation](https://p2.github.io/OAuth2)\n\nOAuth2 requires Xcode 12.4, the built framework can be used on **OS X 10.15** or **iOS 12** and later.\nHappy to accept pull requests, please see [CONTRIBUTING.md](./CONTRIBUTING.md)\n\n### Swift Version\n\nSince the Swift language is constantly evolving I have adopted a versioning scheme mirroring Swift versions:\nthe framework version's **first two digits are always the Swift version** the library is compatible with, see [releases](https://github.com/p2/OAuth2/releases).\nCode compatible with brand new Swift versions are to be found on a separate feature branch named appropriately.\n\n\nUsage\n-----\n\nTo use OAuth2 in your own code, start with `import OAuth2` in your source files.\n\nIn OAuth2 there are [**different kinds of _flows_**](https://tools.ietf.org/html/rfc6749#page-2).\nThis library supports all of them, make sure you're using the correct one for your use-case and authorization server.\nA typical **code grant flow** is used for demo purposes below.\nThe steps for other flows are mostly the same short of instantiating a different subclass and using different client settings.\n\nStill not working?\nSee [site-specific peculiarities](#site-specific-peculiarities).\n\n### 1. Instantiate OAuth2 with a Settings Dictionary\n\nIn this example you'll be building an iOS client to Github, so the code below will be somewhere in a view controller of yours, _maybe_ the app delegate.\n\n```swift\nlet oauth2 = OAuth2CodeGrant(settings: [\n    \"client_id\": \"my_swift_app\",\n    \"client_secret\": \"C7447242\",\n    \"authorize_uri\": \"https://github.com/login/oauth/authorize\",\n    \"token_uri\": \"https://github.com/login/oauth/access_token\",   // code grant only\n    \"redirect_uris\": [\"myapp://oauth/callback\"],   // register your own \"myapp\" scheme in Info.plist\n    \"scope\": \"user repo:status\",\n    \"secret_in_body\": true,    // Github needs this\n    \"keychain\": false,         // if you DON'T want keychain integration\n] as OAuth2JSON)\n```\n\nSee those `redirect_uris`?\nYou can use the scheme you want, but you must **a)** declare the scheme you use in your `Info.plist` and **b)** register the very same URI on the authorization server you connect to.\n\nNote that **as of iOS 9**, you _should_ use [Universal Links](https://developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html) as your redirect URL, rather than a custom app scheme.\nThis prevents others from re-using your URI scheme and intercept the authorization flow.  \nIf you **target iOS 12 and newer** you should be using `ASWebAuthenticationSession`, which makes using your own local redirect scheme secure.\n\nWant to avoid switching to Safari and pop up a SafariViewController or NSPanel?\nSet this:\n\n```swift\noauth2.authConfig.authorizeEmbedded = true\noauth2.authConfig.authorizeContext = \u003c# your UIViewController / NSWindow #\u003e\n```\n\nNeed to specify a separate refresh token URI? You can set the `refresh_uri` in the Settings Dictionary. If specified the library will refresh access tokens using the `refresh_uri` you specified, otherwise it will use the `token_uri`.\n\nNeed to debug? Use a `.debug` or even a `.trace` logger:\n\n```swift\noauth2.logger = OAuth2DebugLogger(.trace)\n```\n\nFor more see [advanced settings](#advanced-settings) below.\n\n\n### 2. Let the Data Loader or Alamofire Take Over\n\nStarting with version 3.0, there is an `OAuth2DataLoader` class that you can use to retrieve data from an API.\nIt will automatically start authorization if needed and will ensure that this works even if you have multiple calls going on.\nFor details on how to configure authorization see step 4 below, in this example we'll use \"embedded\" authorization, meaning we'll show a SFSafariViewController on iOS if the user needs to log in.\n\n[This wiki page has all you need](https://github.com/p2/OAuth2/wiki/Alamofire-5) to easily use OAuth2 with Alamofire instead.\n\n```swift\nlet base = URL(string: \"https://api.github.com\")!\nlet url = base.appendingPathComponent(\"user\")\n\nvar req = oauth2.request(forURL: url)\nreq.setValue(\"application/vnd.github.v3+json\", forHTTPHeaderField: \"Accept\")\n\nself.loader = OAuth2DataLoader(oauth2: oauth2)\nloader.perform(request: req) { response in\n    do {\n        let dict = try response.responseJSON()\n        DispatchQueue.main.async {\n            // you have received `dict` JSON data!\n        }\n    }\n    catch let error {\n        DispatchQueue.main.async {\n            // an error occurred\n        }\n    }\n}\n```\n\n### 3. Make Sure You Intercept the Callback\n\nWhen using the OS browser or the iOS 9+ Safari view controller, you will need to **intercept the callback** in your app delegate and let the OAuth2 instance handle the full URL:\n\n```swift\nfunc application(_ app: UIApplication,\n              open url: URL,\n               options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -\u003e Bool {\n    // you should probably first check if this is the callback being opened\n    if \u003c# check #\u003e {\n        // if your oauth2 instance lives somewhere else, adapt accordingly\n        oauth2.handleRedirectURL(url)\n    }\n}\n```\n\nFor iOS 13 make the callback in `SceneDelegate.swift`\n\n```swift\nfunc scene(_ scene: UIScene, openURLContexts URLContexts: Set\u003cUIOpenURLContext\u003e) {\n\tif let url = URLContexts.first?.url {\n\t\tAppDelegate.shared.oauth2?.handleRedirectURL(url)\n\t}\n}\n```\n\nYou’re all set!\n\n---\n\nIf you want to dig deeper or do authorization yourself, here it goes:\n\n### 4. Manually Authorize the User\n\nBy default the OS browser will be used for authorization if there is no access token present or in the keychain.\n**Starting with iOS 12**, `ASWebAuthenticationSession` will be used when enabling embedded authorization on iOS (previously, starting with iOS 9, `SFSafariViewController` was used instead).\n\nTo start authorization call **`authorize(params:callback:)`** or, to use embedded authorization, the convenience method `authorizeEmbedded(from:callback:)`.\n\nThe login screen will only be **presented if needed** (see [_Manually Performing Authorization](#manually-performing-authorization) below for details) and will automatically **dismiss** the login screen on success.\nSee [_Advanced Settings_](#advanced-settings) for other options.\n\n\n```swift\noauth2.authorize() { authParameters, error in\n    if let params = authParameters {\n        print(\"Authorized! Access token is in `oauth2.accessToken`\")\n        print(\"Authorized! Additional parameters: \\(params)\")\n    }\n    else {\n        print(\"Authorization was canceled or went wrong: \\(error)\")   // error will not be nil\n    }\n}\n\n// for embedded authorization you can simply use:\noauth2.authorizeEmbedded(from: \u003c# presenting view controller / window #\u003e) { ... }\n\n// which is equivalent to:\noauth2.authConfig.authorizeEmbedded = true\noauth2.authConfig.authorizeContext = \u003c# presenting view controller / window #\u003e\noauth2.authorize() { ... }\n```\n\nDon't forget, when using the OS browser or the iOS 9+ Safari view controller, you will need to **intercept the callback** in your app delegate.\nThis is shown under step 2 above.\n\nSee [_Manually Performing Authorization_](#manually-performing-authorization) below for details on how to do this on the Mac.\n\n### 5. Receive Callback\n\nAfter everything completes the callback will be called, **either** with a non-nil _authParameters_ dictionary (which may be empty!), **or** an error.\nThe access and refresh tokens and its expiration dates will already have been extracted and are available as `oauth2.accessToken` and `oauth2.refreshToken` parameters.\nYou only need to inspect the _authParameters_ dictionary if you wish to extract additional information.\n\nFor advanced use outlined below, there is the `afterAuthorizeOrFail` block that you can use on your OAuth2 instance.\nThe `internalAfterAuthorizeOrFail` closure is, as its name suggests, provided for internal purposes – it is exposed for subclassing and compilation reasons and you should not mess with it.\nAs of version 3.0.2, you can no longer use the `onAuthorize` and `onFailure` callback properties, they have been removed entirely.\n\n### 6. Make Requests\n\nYou can now obtain an `OAuth2Request`, which is an already signed `MutableURLRequest`, to retrieve data from your server.\nThis request sets the _Authorization_ header using the access token like so: `Authorization: Bearer {your access token}`.\n\n```swift\nlet req = oauth2.request(forURL: \u003c# resource URL #\u003e)\n// set up your request, e.g. `req.HTTPMethod = \"POST\"`\nlet task = oauth2.session.dataTaskWithRequest(req) { data, response, error in\n    if let error = error {\n        // something went wrong, check the error\n    }\n    else {\n        // check the response and the data\n        // you have just received data with an OAuth2-signed request!\n    }\n}\ntask.resume()\n```\n\nOf course you can use your own `URLSession` with these requests, you don't have to use `oauth2.session`; use [OAuth2DataLoader](https://github.com/p2/OAuth2/blob/main/Sources/Base/OAuth2DataLoader.swift), as shown in step 2, or hand it over to _Alamofire_.\n[Here's all you need](https://github.com/p2/OAuth2/wiki/Alamofire-4) to easily use OAuth2 with Alamofire.\n\n### 7. Cancel Authorization\n\nYou can cancel an ongoing authorization any time by calling `oauth2.abortAuthorization()`.\nThis will cancel ongoing requests (like a code exchange request) or call the callback while you're waiting for a user to login on a webpage.\nThe latter will dismiss embedded login screens or redirect the user back to the app.\n\n### 8. Re-Authorize\n\nIt is safe to always call `oauth2.authorize()` before performing a request.\nYou can also perform the authorization before the first request after your app became active again.\nOr you can always intercept 401s in your requests and call authorize again before re-attempting the request.\n\n### 9. Logout\n\nIf you're storing tokens to the keychain, you can call `forgetTokens()` to throw them away.\n\n**However** your user is likely still logged in to the website, so on the next `authorize()` call, the web view may appear and immediately disappear.\nWhen using the built-in web view on iOS 8, one can use the following snippet to throw away any cookies the app created.\nWith the newer `SFSafariViewController`, or logins performed in the browser, it's probably best to directly **open the logout page** so the user sees the logout happen.\n\n```swift\nlet storage = HTTPCookieStorage.shared\nstorage.cookies?.forEach() { storage.deleteCookie($0) }\n```\n\n\nManually Performing Authorization\n---------------------------------\n\nThe `authorize(params:callback:)` method will:\n\n1. Check if an authorize call is already running, if yes it will abort with an `OAuth2Error.alreadyAuthorizing` error\n2. Check if an access token that has not yet expired is already present (or in the keychain), if not\n3. Check if a refresh token is available, if found\n4. Try to use the refresh token to get a new access token, if it fails\n5. Start the OAuth2 dance by using the `authConfig` settings to determine how to display an authorize screen to the user\n\nYour `oauth2` instance will use an automatically created `URLSession` using an `ephemeralSessionConfiguration()` configuration for its requests, exposed on `oauth2.session`.\nYou can set `oauth2.sessionConfiguration` to your own configuration, for example if you'd like to change timeout values.\nYou can also set `oauth2.sessionDelegate` to your own session delegate if you like.\n\nThe wiki has [the complete call graph](https://github.com/p2/OAuth2/wiki/Call-Graph) of the _authorize()_ method.\nIf you do **not wish this kind of automation**, the manual steps to show and hide the authorize screens are:\n\n**Embedded iOS**:\n\n```swift\nlet url = try oauth2.authorizeURL(params: \u003c# custom parameters or nil #\u003e)\noauth2.authConfig.authorizeEmbeddedAutoDismiss = false\nlet web = try oauth2.authorizer.authorizeSafariEmbedded(from: \u003c# view controller #\u003e, at: url)\noauth2.afterAuthorizeOrFail = { authParameters, error in\n    // inspect error or oauth2.accessToken / authParameters or do something else\n    web.dismissViewControllerAnimated(true, completion: nil)\n}\n```\n\n**Modal Sheet on macOS**:\n\n```swift\nlet window = \u003c# window to present from #\u003e\nlet url = try oauth2.authorizeURL(params: \u003c# custom parameters or nil #\u003e)\nlet sheet = try oauth2.authorizer.authorizeEmbedded(from: window, at: url)\noauth2.afterAuthorizeOrFail = { authParameters, error in\n    // inspect error or oauth2.accessToken / authParameters or do something else\n    window.endSheet(sheet)\n}\n```\n\n**New window on macOS**:\n\n```swift\nlet url = try oauth2.authorizeURL(params: \u003c# custom parameters or nil #\u003e)\nlet windowController = try oauth2.authorizer.authorizeInNewWindow(at: url)\noauth2.afterAuthorizeOrFail = { authParameters, error in\n    // inspect error or oauth2.accessToken / authParameters or do something else\n    windowController.window?.close()\n}\n```\n\n**iOS/macOS browser**:\n\n```swift\nlet url = try oauth2.authorizeURL(params: \u003c# custom parameters or nil #\u003e)\ntry oauth2.authorizer.openAuthorizeURLInBrowser(url)\noauth2.afterAuthorizeOrFail = { authParameters, error in\n    // inspect error or oauth2.accessToken / authParameters or do something else\n}\n```\n\n\n**macOS**\n\nSee the [OAuth2 Sample App][sample]'s AppDelegate class on how to receive the callback URL in your Mac app.\nIf the authorization displays the code to the user, e.g. with Google's `urn:ietf:wg:oauth:2.0:oob` callback URL, you can retrieve the code from the user's pasteboard and continue authorization with:\n\n```swift\nlet pboard = NSPasteboard.general()\nif let pasted = pboard.string(forType: NSPasteboardTypeString) {\n    oauth2.exchangeCodeForToken(pasted)\n}\n```\n\n\nFlows\n-----\n\nBased on which OAuth2 flow that you need you will want to use the correct subclass.\nFor a very nice explanation of OAuth's basics: [The OAuth Bible](http://oauthbible.com/#oauth-2-three-legged).\n\n#### Code Grant\n\nFor a full OAuth 2 code grant flow (`response_type=code`) you want to use the `OAuth2CodeGrant` class.\nThis flow is typically used by applications that can guard their secrets, like server-side apps, and not in distributed binaries.\nIn case an application cannot guard its secret, such as a distributed iOS app, you would use the _implicit grant_ or, in some cases, still a _code grant_ but omitting the client secret.\nIt has however become common practice to still use code grants from mobile devices, including a client secret.\n\nThis class fully supports those flows, it automatically creates a “Basic” Authorization header if the client has a non-nil client secret.\nThis means that you likely **must** specify `client_secret` in your settings; if there is none (like for [Reddit](https://github.com/reddit/reddit/wiki/OAuth2#token-retrieval-code-flow)) specify the empty string.\nIf the site requires client credentials in the request body, set `clientConfig.secretInBody` to true, as explained below.\n\n#### Implicit Grant\n\nAn implicit grant (`response_type=token`) is suitable for apps that are not capable of guarding their secret, such as distributed binaries or client-side web apps.\nUse the `OAuth2ImplicitGrant` class to receive a token and perform requests.\n\nWould be nice to add another code example here, but it's pretty much the same as for the _code grant_.\n\n#### Client Credentials\n\nA 2-legged flow that lets an app authorize itself via its client id and secret.\nInstantiate `OAuth2ClientCredentials`, as usual supplying `client_id` but also a `client_secret` – plus your other configurations – in the settings dict, and you should be good to go.\n\n#### Username and Password\n\nThe _Resource Owner Password Credentials Grant_ is supported with the `OAuth2PasswordGrant` subclass.\nCreate an instance as shown above, set its `username` and `password` properties, then call `authorize()`.\n\n### Device Grant\n\nThe [OAuth 2.0 Device Authorization Grant](https://datatracker.ietf.org/doc/html/rfc8628) flow is implemented in the `OAuth2DeviceGrant` subclass.\nAlthough this flow is designed for devices that either lack a browser to perform a user-agent-based authorization or are input constrained, it is also very useful for applications not allowed to [start their own webserver (loopback URL) or register a custom URL scheme](https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uris-native-apps/) to finish the authorization code grant flow.\nTo initiate the device grant flow, the `deviceAuthorizeURL` needs to be correctly configured to point towards the device authorization endpoint. By calling the `OAuth2DeviceGrant.start(useNonTextualTransmission:params:completion:)` method, the client obtains [all necessary details](https://datatracker.ietf.org/doc/html/rfc8628#section-3.2) to complete the authorization on a secondary device or in the system browser.\n\n\n\nSite-Specific Peculiarities\n---------------------------\n\nSome sites might not strictly adhere to the OAuth2 flow, from returning data differently like Facebook to omitting mandatory return parameters like Instagram \u0026 co.\nThe framework deals with those deviations by creating site-specific subclasses and/or configuration details.\nIf you need to pass additional **headers** or **parameters**, you can supply these in the settings dict like so:\n\n```swift\nlet oauth2 = OAuth2CodeGrant(settings: [\n    \"client_id\": \"...\",\n    ...\n    \"headers\": [\"Accept\": \"application/vnd.github.v3+json\"],\n    \"parameters\": [\"duration\": \"permanent\"],\n] as OAuth2JSON)\n```\n\n- [GitHub](https://github.com/p2/OAuth2/wiki/GitHub)\n- [Facebook](https://github.com/p2/OAuth2/wiki/Facebook)\n- [Reddit](https://github.com/p2/OAuth2/wiki/Reddit)\n- [Google](https://github.com/p2/OAuth2/wiki/Google)\n- [LinkedIn](https://github.com/p2/OAuth2/wiki/LinkedIn)\n- [Instagram, Bitly, Pinterest, ...](https://github.com/p2/OAuth2/wiki/Instagram,-Bitly,-Pinterest-and-others)\n- [Uber](https://github.com/p2/OAuth2/wiki/Uber)\n- [BitBucket](https://github.com/p2/OAuth2/wiki/BitBucket)\n\n\nAdvanced Settings\n-----------------\n\nThe main configuration you'll use with `oauth2.authConfig` is whether or not to use an embedded login:\n\n    oauth2.authConfig.authorizeEmbedded = true\n\nSimilarly, if you want to take care of dismissing the login screen yourself (not possible with the newer authorization sessions mentioned below):\n\n    oauth2.authConfig.authorizeEmbeddedAutoDismiss = false\n\nSome sites also want the client-id/secret combination in the request _body_, not in the _Authorization_ header:\n\n    oauth2.clientConfig.secretInBody = true\n    // or in your settings:\n    \"secret_in_body\": true\n\nSometimes you also need to provide additional authorization parameters.\nThis can be done in 3 ways:\n\n    oauth2.authParameters = [\"duration\": \"permanent\"]\n    // or in your settings:\n    \"parameters\": [\"duration\": \"permanent\"]\n    // or when you authorize manually:\n    oauth2.authorize(params: [\"duration\": \"permanent\"]) { ... }\n\nSimilar is how you specify custom HTTP headers:\n\n    oauth2.clientConfig.authHeaders = [\"Accept\": \"application/json, text/plain\"]\n    // or in your settings:\n    \"headers\": [\"Accept\": \"application/json, text/plain\"]\n\nSome sites (e.g. Slack) validate the User-Agent string against supported browser versions, which may not match WebKit's default in embedded mode. The embedded mode User-Agent may be overriden with:\n\n    oauth2.customUserAgent = \"Version/15.6.1 Safari\"\n    // or in your settings:\n    \"custom_user_agent\": \"Your string of choice\"\n\nStarting with version 2.0.1 on iOS 9, `SFSafariViewController` will be used for embedded authorization.\nStarting after version 4.2, on iOS 11 (`SFAuthenticationSession`) and iOS 12 (`ASWebAuthenticationSession`), you can opt-in to these newer authorization session view controllers:\n\n    oauth2.authConfig.ui.useAuthenticationSession = true\n\nTo revert to the old custom `OAuth2WebViewController`, which you _should not do_ because `ASWebAuthenticationSession` is way more secure:\n\n    oauth2.authConfig.ui.useSafariView = false\n\nTo customize the _go back_ button when using `OAuth2WebViewController` on iOS 8 and older:\n\n    oauth2.authConfig.ui.backButton = \u003c# UIBarButtonItem(...) #\u003e\n\nSee below for settings about [the keychain](#keychain) and [PKCE](#pkce).\n\nUsage with Alamofire\n--------------------\n\nYou'll get the best experience when using Alamofire v4 or newer and OAuth2 v3 and newer:\n\n- How to use Alamofire [version 4 and newer](https://github.com/p2/OAuth2/wiki/Alamofire-4)\n- How to use [version 3 and older](https://github.com/p2/OAuth2/wiki/Alamofire-3)\n\n\nDynamic Client Registration\n---------------------------\n\nThere is support for [dynamic client registration](https://tools.ietf.org/html/rfc7591).\nIf during setup `registration_url` is set but `client_id` is not, the `authorize()` call automatically attempts to register the client before continuing to the actual authorization.\nClient credentials returned from registration are stored to the keychain.\n\nThe `OAuth2DynReg` class is responsible for handling client registration.\nYou can use its `register(client:callback:)` method manually if you need to.\nRegistration parameters are taken from the client's configuration.\n\n```swift\nlet oauth2 = OAuth2...()\noauth2.registerClientIfNeeded() { error in\n    if let error = error {\n        // registration failed\n    }\n    else {\n        // client was registered\n    }\n}\n```\n\n```swift\nlet oauth2 = OAuth2...()\nlet dynreg = OAuth2DynReg()\ndynreg.register(client: oauth2) { params, error in\n    if let error = error {\n        // registration failed\n    }\n    else {\n        // client was registered with `params`\n    }\n}\n```\n\nPKCE\n----\n\nPKCE support is controlled by the `useProofKeyForCodeExchange` property, and the `use_pkce` key in the settings dictionary.\nIt is disabled by default. When enabled, a new code verifier string is generated for every authorization request. \n\n\nKeychain\n--------\n\nThis framework can transparently use the iOS and macOS keychain.\nIt is controlled by the `useKeychain` property, which can be disabled during initialization with the `keychain` settings dictionary key.\nSince this is **enabled by default**, if you do _not_ turn it off during initialization, the keychain will be queried for tokens and client credentials related to the authorization URL.\nIf you turn it off _after_ initialization, the keychain will be queried for existing tokens, but new tokens will not be written to the keychain.\n\nIf you want to delete the tokens from keychain, i.e. **log the user out** completely, call `forgetTokens()`.\nIf you have dynamically registered your client and want to start anew, you can call `forgetClient()`.\n\nIdeally, access tokens get delivered with an \"expires_in\" parameter that tells you how long the token is valid.\nIf it is missing the framework will still use those tokens if one is found in the keychain and not re-perform the OAuth dance.\nYou will need to intercept 401s and re-authorize if an access token has expired but the framework has still pulled it from the keychain.\nThis behavior can be turned off by supplying `token_assume_unexpired: false` in settings or setting `clientConfig.accessTokenAssumeUnexpired` to false.\n\nThese are the settings dictionary keys you can use for more control:\n\n- `keychain`: a bool on whether to use keychain or not, true by default\n- `keychain_access_mode`: a string value for keychain kSecAttrAccessible attribute, \"kSecAttrAccessibleWhenUnlocked\" by default, you can change this to e.g. \"kSecAttrAccessibleAfterFirstUnlock\" if you need the tokens to be available when the phone is locked.\n- `keychain_access_group`: a string value for keychain kSecAttrAccessGroup attribute, nil by default\n- `keychain_account_for_client_credentials`: the name to use to identify client credentials in the keychain, \"clientCredentials\" by default\n- `keychain_account_for_tokens`: the name to use to identify the tokens in the keychain, \"currentTokens\" by default\n\nInstallation\n------------\n\nYou can use the _Swift Package Manager_, _git_ or _Carthage_.\nThe preferred way is to use the _Swift Package Manager_.\n\n#### Swift Package Manager\n\nIn Xcode 11 and newer, choose \"File\" from the Xcode Menu, then \"Swift Packages\" » \"Add Package Dependency...\" and paste the URL of this repo: `https://github.com/p2/OAuth2.git`. Pick a version and Xcode should do the rest.\n\n#### Carthage\n\nInstallation via Carthage is easy enough:\n\n```ruby\ngithub \"p2/OAuth2\" ~\u003e 4.2\n```\n\n#### git\n\nUsing Terminal.app, clone the OAuth2 repository, best into a subdirectory of your app project:  \n\n    $ cd path/to/your/app\n    $ git clone --recursive https://github.com/p2/OAuth2.git\n\nIf you're using git you'll want to add it as a submodule.\nOnce cloning completes, open your app project in Xcode and add `OAuth2.xcodeproj` to your app:\n\n![Adding to Xcode](assets/step-adding.png)\n\nNow link the framework to your app:\n\n![Linking](assets/step-linking.png)\n\nThese three steps are needed to:\n\n1. Make your App also build the framework\n2. Link the framework into your app\n3. Embed the framework in your app when distributing\n\n\nLicense\n-------\n\nThis code is released under the [_Apache 2.0 license_](LICENSE.txt), which means that you can use it in open as well as closed source projects.\nSince there is no `NOTICE` file there is nothing that you have to include in your product.\n\n\n[sample]: https://github.com/p2/OAuth2App\n","funding_links":[],"categories":["Authentication","Libs","HarmonyOS","Swift","Network [🔝](#readme)"],"sub_categories":["Network","Other free courses","Getting Started","Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp2%2FOAuth2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp2%2FOAuth2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp2%2FOAuth2/lists"}