{"id":19593055,"url":"https://github.com/thoughtbot/superb","last_synced_at":"2025-09-06T16:44:10.181Z","repository":{"id":62456324,"uuid":"75952875","full_name":"thoughtbot/Superb","owner":"thoughtbot","description":"Pluggable HTTP authentication for Swift.","archived":false,"fork":false,"pushed_at":"2021-09-24T16:05:16.000Z","size":289,"stargazers_count":201,"open_issues_count":7,"forks_count":7,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-08-01T14:44:48.610Z","etag":null,"topics":["authentication","authorization","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thoughtbot.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":null,"support":null}},"created_at":"2016-12-08T15:59:37.000Z","updated_at":"2025-01-20T12:52:31.000Z","dependencies_parsed_at":"2022-11-02T00:01:00.119Z","dependency_job_id":null,"html_url":"https://github.com/thoughtbot/Superb","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/thoughtbot/Superb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2FSuperb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2FSuperb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2FSuperb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2FSuperb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thoughtbot","download_url":"https://codeload.github.com/thoughtbot/Superb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtbot%2FSuperb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273933876,"owners_count":25193599,"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","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","authorization","swift"],"created_at":"2024-11-11T08:37:58.212Z","updated_at":"2025-09-06T16:44:10.158Z","avatar_url":"https://github.com/thoughtbot.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Superb [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n\nPluggable HTTP authentication for Swift.\n\n**Advantages**\n\n- Safe, **secure token storage** in the iOS Keychain.\n- Automatic handling of 401 responses and **reauthentication**.\n- Scales to handle many concurrent requests in a **thread-safe** way.\n- Stays out of your way until you need it with a simple, **minimal API**.\n- Promotes Apple's [Authentication Guidelines][hig] by \"delaying sign-in as long as possible\".\n- Supports **adapters** for any number of authentication providers.\n- **Extensible** without requiring any source modifications or pull requests.\n\n**Caveats**\n\n- *Opinionated* about user experience.\n\n[hig]: https://developer.apple.com/ios/human-interface-guidelines/interaction/authentication/\n\n## Usage\n\n### Example: GitHub OAuth Authentication\n\nWhen you register the app with your OAuth provider, you will give a redirect\nURI. This URI must use a URL scheme that is registered for your app in your\napp's `Info.plist`.\n\nSuperb allows your app to support multiple authentication providers via a\nregistration mechanism. iOS apps have a single entrypoint for URLs, so Superb\nsearches through the registered providers to find the correct one to handle the\nredirect URL.\n\n```swift\n// GitHub+Providers.swift\n\nimport Superb\nimport SuperbGitHub\n\nextension GitHubOAuthProvider {\n  static var shared: GitHubOAuthProvider {\n    // Register a provider to handle callback URLs\n    return Superb.register(\n      GitHubOAuthProvider(\n        clientId: \"\u003cyour client id\u003e\",\n        clientSecret: \"\u003cyour client secret\u003e\",\n        redirectURI: URL(string: \"\u003cyour chosen redirect URI\u003e\")!\n      )\n    )\n  }\n}\n```\n\n```swift\n// AppDelegate.swift\n\n@UIApplicationMain\nfinal class AppDelegate: UIResponder, UIApplicationDelegate {\n  // ...\n\n  func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey: Any]) -\u003e Bool {\n    // Pass the URL and options off to Superb.\n    return Superb.handleAuthenticationRedirect(url, options: options)\n  }\n}\n```\n\nThen, in our API client, we can use `RequestAuthorizer` to fence the code that\nmust be run with authentication, using `RequestAuthorizer.performAuthorized()`.\n\n```swift\n// GitHubAPIClient.swift\n\nstruct GitHubAPIClient {\n  static let oauthClient = GitHubAPIClient(\n    requestAuthorizer: RequestAuthorizer(\n      authorizationProvider: GitHubOAuthProvider.shared\n    )\n  )\n\n  private let authorizer: RequestAuthorizerProtocol\n\n  init(requestAuthorizer: RequestAuthorizerProtocol) {\n    authorizer = requestAuthorizer\n  }\n\n  // An authorized request to get the current user's profile.\n  func getProfile(completionHandler: @escaping (Result\u003cProfile, SuperbError\u003e) -\u003e Void) {\n    let request = URLRequest(url: URL(string: \"https://api.github.com/user\")!)\n\n    authorizer.performAuthorized(request) { result in\n      switch result {\n      case let .success(data, _):\n        let profile = parseProfile(from: data)\n        completionHandler(.success(profile))\n\n      case let .failure(error):\n        completionHandler(.failure(error))\n      }\n    }\n  }\n\n  // An unauthorized request.\n  func getZen(completionHandler: @escaping (Result\u003cString, SuperbError\u003e) -\u003e Void) {\n    let request = URLRequest(url: URL(string: \"https://api.github.com/zen\")!)\n\n    URLSession.shared.dataTask(with: request) { data, _, error in\n      let result = parseZen(data, error)\n      completionHandler(result)\n    }.resume()\n  }\n}\n\n// later\nlet api = GitHubAPIClient.oauthClient\n\napi.getProfile { result in\n  // ...\n}\n```\n\n## List of Authentication Providers\n\n- [GitHub](https://github.com/thoughtbot/SuperbGitHub)\n\n## Installation\n\n### [Carthage][]\n\n[Carthage]: https://github.com/Carthage/Carthage\n\nAdd the following to your Cartfile:\n\n```\ngithub \"thoughtbot/Superb\" ~\u003e 0.2\n```\n\nThen run `carthage update`.\n\nFollow the current instructions in [Carthage's README][carthage-installation]\nfor up to date installation instructions.\n\nYou will need to embed both `Superb.framework` and `Result.framework` in your\napplication.\n\n[carthage-installation]: https://github.com/Carthage/Carthage#adding-frameworks-to-an-application\n\n### [CocoaPods][]\n\n[CocoaPods]: https://cocoapods.org\n\nAdd the following to your [Podfile](https://guides.cocoapods.org/using/the-podfile.html):\n\n```ruby\npod \"Superb\", \"~\u003e 0.2.0\"\n```\n\nYou will also need to make sure you're opting into using frameworks:\n\n```ruby\nuse_frameworks!\n```\n\nThen run `pod install`.\n\n## Troubleshooting\n\n### Authentication always fails when using OAuth\n\n#### You forgot to call `Superb.register`.\n\nIf you do not call `Superb.register` then your authentication provider will not\nhave a chance to receive callback URLs.\n\n## Contributing\n\nSee the [CONTRIBUTING] document. Thank you, [contributors]!\n\n[CONTRIBUTING]: CONTRIBUTING.md\n[contributors]: https://github.com/thoughtbot/Superb/graphs/contributors\n\n## License\n\nSuperb is Copyright (c) 2017 thoughtbot, inc. It is free software, and may be\nredistributed under the terms specified in the [LICENSE] file.\n\n[LICENSE]: /LICENSE\n\n## About\n\n![thoughtbot](http://presskit.thoughtbot.com/images/thoughtbot-logo-for-readmes.svg)\n\nSuperb is maintained and funded by thoughtbot, inc. The names and logos for\nthoughtbot are trademarks of thoughtbot, inc.\n\nWe love open source software! See [our other projects][community] or look at\nour product [case studies] and [hire us][hire] to help build your iOS app.\n\n[community]: https://thoughtbot.com/community?utm_source=github\n[case studies]: https://thoughtbot.com/work?utm_source=github\n[hire]: https://thoughtbot.com/hire-us?utm_source=github\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtbot%2Fsuperb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthoughtbot%2Fsuperb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtbot%2Fsuperb/lists"}