Top Related Projects
The most scalable and customizable OpenID Certified™ OpenID Connect and OAuth Provider on the market. Become an OpenID Connect and OAuth2 Provider over night. Broad support for related RFCs. Written in Go, cloud native, headless, API-first. Available as a service on Ory Network and for self-hosters.
OpenID Certified™ OAuth 2.0 Authorization Server implementation for Node.js
Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
Open Source Identity and Access Management For Modern Applications and Services
A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers.
A spec compliant, secure by default PHP OAuth 2.0 Server
Quick Overview
p2/OAuth2 is a PHP library for implementing OAuth 2.0 authorization and authentication. It provides a robust and flexible solution for integrating OAuth 2.0 into PHP applications, supporting various grant types and offering easy-to-use interfaces for both client and server implementations.
Pros
- Comprehensive support for multiple OAuth 2.0 grant types
- Well-documented and actively maintained
- Flexible and extensible architecture
- Includes both client and server implementations
Cons
- Steeper learning curve for beginners
- Requires PHP 7.1 or higher
- May be overkill for simple OAuth implementations
- Limited built-in support for specific OAuth providers
Code Examples
- Creating an OAuth 2.0 client:
$client = new OAuth2\Client('client_id', 'client_secret');
- Requesting an access token using the Authorization Code grant:
$response = $client->getAccessToken('authorization_code', [
'code' => $_GET['code'],
'redirect_uri' => 'https://example.com/callback'
]);
- Making an authenticated API request:
$request = $client->getAuthenticatedRequest(
'GET',
'https://api.example.com/user',
$accessToken
);
$response = $client->getResponse($request);
Getting Started
- Install the library using Composer:
composer require league/oauth2-client
- Set up the OAuth 2.0 client:
require_once 'vendor/autoload.php';
$client = new OAuth2\Client([
'clientId' => 'your_client_id',
'clientSecret' => 'your_client_secret',
'redirectUri' => 'https://example.com/callback'
]);
// Generate authorization URL
$authUrl = $client->getAuthorizationUrl();
// Redirect the user to the authorization URL
header('Location: ' . $authUrl);
exit;
- Handle the callback and request an access token:
if (isset($_GET['code'])) {
$token = $client->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// Use the token to make authenticated API requests
// ...
}
Competitor Comparisons
The most scalable and customizable OpenID Certified™ OpenID Connect and OAuth Provider on the market. Become an OpenID Connect and OAuth2 Provider over night. Broad support for related RFCs. Written in Go, cloud native, headless, API-first. Available as a service on Ory Network and for self-hosters.
Pros of Hydra
- More comprehensive OAuth2 and OpenID Connect server implementation
- Supports advanced features like JSON Web Key rotation and dynamic client registration
- Active development with frequent updates and strong community support
Cons of Hydra
- Steeper learning curve due to its extensive feature set
- Requires more setup and configuration compared to simpler libraries
- Higher resource consumption for small-scale applications
Code Comparison
OAuth2 (PHP):
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => 'your-client-id',
'clientSecret' => 'your-client-secret',
'redirectUri' => 'https://example.com/callback-url',
'urlAuthorize' => 'https://example.com/oauth/authorize',
'urlAccessToken' => 'https://example.com/oauth/token',
'urlResourceOwnerDetails' => 'https://example.com/api/user'
]);
Hydra (Go):
import "github.com/ory/hydra-client-go"
configuration := hydra.NewConfiguration()
configuration.Servers = hydra.ServerConfigurations{{URL: "http://localhost:4444"}}
client := hydra.NewAPIClient(configuration)
_, _, err := client.OAuth2Api.AcceptOAuth2ConsentRequest(context.Background()).
ConsentChallenge("challenge").
AcceptOAuth2ConsentRequest(hydra.AcceptOAuth2ConsentRequest{
GrantScope: []string{"openid", "offline"},
}).Execute()
OpenID Certified™ OAuth 2.0 Authorization Server implementation for Node.js
Pros of node-oidc-provider
- Comprehensive OpenID Connect implementation
- Active development and maintenance
- Extensive documentation and examples
Cons of node-oidc-provider
- Steeper learning curve due to complexity
- Requires more setup and configuration
- Potentially overkill for simple OAuth2 use cases
Code Comparison
node-oidc-provider:
const Provider = require('oidc-provider');
const configuration = {
clients: [{ client_id: 'foo', client_secret: 'bar', redirect_uris: ['http://localhost:8080/cb'] }],
};
const oidc = new Provider('http://localhost:3000', configuration);
OAuth2:
$server = new OAuth2\Server($storage);
$server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
Summary
node-oidc-provider offers a more comprehensive OpenID Connect solution with active development and extensive documentation. However, it may be more complex to set up and potentially excessive for simple OAuth2 needs. OAuth2, on the other hand, provides a simpler implementation focused on OAuth2 functionality, which may be sufficient for basic use cases but lacks the full OpenID Connect feature set.
Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
Pros of Spring Security OAuth
- Comprehensive integration with Spring ecosystem
- Robust support for various OAuth2 flows and grant types
- Extensive documentation and community support
Cons of Spring Security OAuth
- Steeper learning curve for developers new to Spring
- Heavier footprint and potential overhead for simpler applications
- Deprecated in favor of Spring Security 5.x OAuth2 support
Code Comparison
Spring Security OAuth:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("clientId")
.secret("secret")
.authorizedGrantTypes("authorization_code")
.scopes("read", "write");
}
}
OAuth2:
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => 'demoapp',
'clientSecret' => 'demopass',
'redirectUri' => 'https://example.com/callback-url',
'urlAuthorize' => 'https://example.com/oauth/authorize',
'urlAccessToken' => 'https://example.com/oauth/token',
'urlResourceOwnerDetails' => 'https://example.com/api/user'
]);
The Spring Security OAuth example showcases its tight integration with Spring's configuration system, while the OAuth2 example demonstrates a more straightforward setup for PHP applications. Spring Security OAuth offers more built-in features and customization options, but OAuth2 provides a simpler, language-agnostic approach that may be easier for some developers to implement and maintain.
Open Source Identity and Access Management For Modern Applications and Services
Pros of Keycloak
- Comprehensive identity and access management solution with a wide range of features
- Supports multiple protocols including OAuth 2.0, OpenID Connect, and SAML
- Offers a user-friendly admin console for easy management and configuration
Cons of Keycloak
- More complex setup and configuration compared to OAuth2
- Higher resource requirements due to its extensive feature set
- Steeper learning curve for developers new to identity management systems
Code Comparison
OAuth2 (Python):
from oauth2 import Provider
class MyProvider(Provider):
def validate_client(self, client_id, client_secret, request):
# Implement client validation logic
Keycloak (Java):
import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.KeycloakDeployment;
public class CustomKeycloakConfigResolver implements KeycloakConfigResolver {
@Override
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
// Implement custom configuration resolution
}
}
The code snippets demonstrate the different approaches to customization in each project. OAuth2 focuses on provider implementation, while Keycloak offers more advanced configuration options through its adapter system.
A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers.
Pros of oauth2-proxy
- More actively maintained with frequent updates and contributions
- Supports a wider range of authentication providers and protocols
- Offers additional features like session management and custom templates
Cons of oauth2-proxy
- More complex setup and configuration process
- Heavier resource usage due to additional features
- Steeper learning curve for newcomers
Code Comparison
OAuth2 (PHP):
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => 'your-client-id',
'clientSecret' => 'your-client-secret',
'redirectUri' => 'https://example.com/callback-url',
'urlAuthorize' => 'https://example.com/oauth/authorize',
'urlAccessToken' => 'https://example.com/oauth/token',
'urlResourceOwnerDetails' => 'https://example.com/api/user'
]);
oauth2-proxy (Go):
func main() {
flagSet := flag.NewFlagSet("oauth2-proxy", flag.ExitOnError)
opts := options.NewOptions()
opts.AddFlags(flagSet)
_ = flagSet.Parse(os.Args[1:])
validator := NewValidator(opts.EmailDomains, opts.AuthenticatedEmailsFile)
oauthproxy := NewOAuthProxy(opts, validator)
// ...
}
The OAuth2 library focuses on providing a simple OAuth2 client implementation in PHP, while oauth2-proxy is a full-featured reverse proxy with built-in OAuth2 authentication support written in Go. oauth2-proxy offers more advanced features and flexibility but requires more setup and configuration compared to the straightforward OAuth2 library.
A spec compliant, secure by default PHP OAuth 2.0 Server
Pros of oauth2-server
- More actively maintained with frequent updates
- Comprehensive documentation and examples
- Supports a wider range of grant types and features
Cons of oauth2-server
- Steeper learning curve for beginners
- Requires more configuration and setup
Code Comparison
OAuth2 (p2/OAuth2):
$server = new OAuth2\Server();
$server->addGrantType(new OAuth2\GrantType\AuthorizationCode($storage));
$server->handleTokenRequest(OAuth2\Request::createFromGlobals())->send();
oauth2-server (thephpleague/oauth2-server):
$server = new \League\OAuth2\Server\AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKey,
$encryptionKey
);
$server->enableGrantType(new \League\OAuth2\Server\Grant\AuthCodeGrant($authCodeRepository, $refreshTokenRepository, $authCodeTTL));
Both libraries provide OAuth2 server implementations, but oauth2-server offers more flexibility and features at the cost of increased complexity. OAuth2 is simpler to set up but may lack some advanced functionality. The code comparison shows that oauth2-server requires more initial configuration but provides greater customization options.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
OAuth2
OAuth2 frameworks for macOS, iOS and tvOS written in Swift 5.
- â¤µï¸ Installation
- ð Usage
- ð¥ Sample macOS app (with data loader examples)
- ð Technical Documentation
OAuth2 requires Xcode 12.4, the built framework can be used on OS X 10.15 or iOS 12 and later. Happy to accept pull requests, please see CONTRIBUTING.md
Swift Version
Since the Swift language is constantly evolving I have adopted a versioning scheme mirroring Swift versions: the framework version's first two digits are always the Swift version the library is compatible with, see releases. Code compatible with brand new Swift versions are to be found on a separate feature branch named appropriately.
Usage
To use OAuth2 in your own code, start with import OAuth2
in your source files.
In OAuth2 there are different kinds of flows. This library supports all of them, make sure you're using the correct one for your use-case and authorization server. A typical code grant flow is used for demo purposes below. The steps for other flows are mostly the same short of instantiating a different subclass and using different client settings.
Still not working? See site-specific peculiarities.
1. Instantiate OAuth2 with a Settings Dictionary
In 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.
let oauth2 = OAuth2CodeGrant(settings: [
"client_id": "my_swift_app",
"client_secret": "C7447242",
"authorize_uri": "https://github.com/login/oauth/authorize",
"token_uri": "https://github.com/login/oauth/access_token", // code grant only
"redirect_uris": ["myapp://oauth/callback"], // register your own "myapp" scheme in Info.plist
"scope": "user repo:status",
"secret_in_body": true, // Github needs this
"keychain": false, // if you DON'T want keychain integration
] as OAuth2JSON)
See those redirect_uris
?
You 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.
Note that as of iOS 9, you should use Universal Links as your redirect URL, rather than a custom app scheme.
This prevents others from re-using your URI scheme and intercept the authorization flow.
If you target iOS 12 and newer you should be using ASWebAuthenticationSession
, which makes using your own local redirect scheme secure.
Want to avoid switching to Safari and pop up a SafariViewController or NSPanel? Set this:
oauth2.authConfig.authorizeEmbedded = true
oauth2.authConfig.authorizeContext = <# your UIViewController / NSWindow #>
Need 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
.
Need to debug? Use a .debug
or even a .trace
logger:
oauth2.logger = OAuth2DebugLogger(.trace)
For more see advanced settings below.
2. Let the Data Loader or Alamofire Take Over
Starting with version 3.0, there is an OAuth2DataLoader
class that you can use to retrieve data from an API.
It will automatically start authorization if needed and will ensure that this works even if you have multiple calls going on.
For 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.
This wiki page has all you need to easily use OAuth2 with Alamofire instead.
let base = URL(string: "https://api.github.com")!
let url = base.appendingPathComponent("user")
var req = oauth2.request(forURL: url)
req.setValue("application/vnd.github.v3+json", forHTTPHeaderField: "Accept")
self.loader = OAuth2DataLoader(oauth2: oauth2)
loader.perform(request: req) { response in
do {
let dict = try response.responseJSON()
DispatchQueue.main.async {
// you have received `dict` JSON data!
}
}
catch let error {
DispatchQueue.main.async {
// an error occurred
}
}
}
3. Make Sure You Intercept the Callback
When 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:
func application(_ app: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey: Any] = [:]) -> Bool {
// you should probably first check if this is the callback being opened
if <# check #> {
// if your oauth2 instance lives somewhere else, adapt accordingly
oauth2.handleRedirectURL(url)
}
}
For iOS 13 make the callback in SceneDelegate.swift
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
AppDelegate.shared.oauth2?.handleRedirectURL(url)
}
}
Youâre all set!
If you want to dig deeper or do authorization yourself, here it goes:
4. Manually Authorize the User
By default the OS browser will be used for authorization if there is no access token present or in the keychain.
Starting with iOS 12, ASWebAuthenticationSession
will be used when enabling embedded authorization on iOS (previously, starting with iOS 9, SFSafariViewController
was used instead).
To start authorization call authorize(params:callback:)
or, to use embedded authorization, the convenience method authorizeEmbedded(from:callback:)
.
The login screen will only be presented if needed (see _Manually Performing Authorization below for details) and will automatically dismiss the login screen on success. See Advanced Settings for other options.
oauth2.authorize() { authParameters, error in
if let params = authParameters {
print("Authorized! Access token is in `oauth2.accessToken`")
print("Authorized! Additional parameters: \(params)")
}
else {
print("Authorization was canceled or went wrong: \(error)") // error will not be nil
}
}
// for embedded authorization you can simply use:
oauth2.authorizeEmbedded(from: <# presenting view controller / window #>) { ... }
// which is equivalent to:
oauth2.authConfig.authorizeEmbedded = true
oauth2.authConfig.authorizeContext = <# presenting view controller / window #>
oauth2.authorize() { ... }
Don'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. This is shown under step 2 above.
See Manually Performing Authorization below for details on how to do this on the Mac.
5. Receive Callback
After everything completes the callback will be called, either with a non-nil authParameters dictionary (which may be empty!), or an error.
The access and refresh tokens and its expiration dates will already have been extracted and are available as oauth2.accessToken
and oauth2.refreshToken
parameters.
You only need to inspect the authParameters dictionary if you wish to extract additional information.
For advanced use outlined below, there is the afterAuthorizeOrFail
block that you can use on your OAuth2 instance.
The 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.
As of version 3.0.2, you can no longer use the onAuthorize
and onFailure
callback properties, they have been removed entirely.
6. Make Requests
You can now obtain an OAuth2Request
, which is an already signed MutableURLRequest
, to retrieve data from your server.
This request sets the Authorization header using the access token like so: Authorization: Bearer {your access token}
.
let req = oauth2.request(forURL: <# resource URL #>)
// set up your request, e.g. `req.HTTPMethod = "POST"`
let task = oauth2.session.dataTaskWithRequest(req) { data, response, error in
if let error = error {
// something went wrong, check the error
}
else {
// check the response and the data
// you have just received data with an OAuth2-signed request!
}
}
task.resume()
Of course you can use your own URLSession
with these requests, you don't have to use oauth2.session
; use OAuth2DataLoader, as shown in step 2, or hand it over to Alamofire.
Here's all you need to easily use OAuth2 with Alamofire.
7. Cancel Authorization
You can cancel an ongoing authorization any time by calling oauth2.abortAuthorization()
.
This 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.
The latter will dismiss embedded login screens or redirect the user back to the app.
8. Re-Authorize
It is safe to always call oauth2.authorize()
before performing a request.
You can also perform the authorization before the first request after your app became active again.
Or you can always intercept 401s in your requests and call authorize again before re-attempting the request.
9. Logout
If you're storing tokens to the keychain, you can call forgetTokens()
to throw them away.
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.
When using the built-in web view on iOS 8, one can use the following snippet to throw away any cookies the app created.
With 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.
let storage = HTTPCookieStorage.shared
storage.cookies?.forEach() { storage.deleteCookie($0) }
Manually Performing Authorization
The authorize(params:callback:)
method will:
- Check if an authorize call is already running, if yes it will abort with an
OAuth2Error.alreadyAuthorizing
error - Check if an access token that has not yet expired is already present (or in the keychain), if not
- Check if a refresh token is available, if found
- Try to use the refresh token to get a new access token, if it fails
- Start the OAuth2 dance by using the
authConfig
settings to determine how to display an authorize screen to the user
Your oauth2
instance will use an automatically created URLSession
using an ephemeralSessionConfiguration()
configuration for its requests, exposed on oauth2.session
.
You can set oauth2.sessionConfiguration
to your own configuration, for example if you'd like to change timeout values.
You can also set oauth2.sessionDelegate
to your own session delegate if you like.
The wiki has the complete call graph of the authorize() method. If you do not wish this kind of automation, the manual steps to show and hide the authorize screens are:
Embedded iOS:
let url = try oauth2.authorizeURL(params: <# custom parameters or nil #>)
oauth2.authConfig.authorizeEmbeddedAutoDismiss = false
let web = try oauth2.authorizer.authorizeSafariEmbedded(from: <# view controller #>, at: url)
oauth2.afterAuthorizeOrFail = { authParameters, error in
// inspect error or oauth2.accessToken / authParameters or do something else
web.dismissViewControllerAnimated(true, completion: nil)
}
Modal Sheet on macOS:
let window = <# window to present from #>
let url = try oauth2.authorizeURL(params: <# custom parameters or nil #>)
let sheet = try oauth2.authorizer.authorizeEmbedded(from: window, at: url)
oauth2.afterAuthorizeOrFail = { authParameters, error in
// inspect error or oauth2.accessToken / authParameters or do something else
window.endSheet(sheet)
}
New window on macOS:
let url = try oauth2.authorizeURL(params: <# custom parameters or nil #>)
let windowController = try oauth2.authorizer.authorizeInNewWindow(at: url)
oauth2.afterAuthorizeOrFail = { authParameters, error in
// inspect error or oauth2.accessToken / authParameters or do something else
windowController.window?.close()
}
iOS/macOS browser:
let url = try oauth2.authorizeURL(params: <# custom parameters or nil #>)
try oauth2.authorizer.openAuthorizeURLInBrowser(url)
oauth2.afterAuthorizeOrFail = { authParameters, error in
// inspect error or oauth2.accessToken / authParameters or do something else
}
macOS
See the OAuth2 Sample App's AppDelegate class on how to receive the callback URL in your Mac app.
If 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:
let pboard = NSPasteboard.general()
if let pasted = pboard.string(forType: NSPasteboardTypeString) {
oauth2.exchangeCodeForToken(pasted)
}
Flows
Based on which OAuth2 flow that you need you will want to use the correct subclass. For a very nice explanation of OAuth's basics: The OAuth Bible.
Code Grant
For a full OAuth 2 code grant flow (response_type=code
) you want to use the OAuth2CodeGrant
class.
This flow is typically used by applications that can guard their secrets, like server-side apps, and not in distributed binaries.
In 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.
It has however become common practice to still use code grants from mobile devices, including a client secret.
This class fully supports those flows, it automatically creates a âBasicâ Authorization header if the client has a non-nil client secret.
This means that you likely must specify client_secret
in your settings; if there is none (like for Reddit) specify the empty string.
If the site requires client credentials in the request body, set clientConfig.secretInBody
to true, as explained below.
Implicit Grant
An 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.
Use the OAuth2ImplicitGrant
class to receive a token and perform requests.
Would be nice to add another code example here, but it's pretty much the same as for the code grant.
Client Credentials
A 2-legged flow that lets an app authorize itself via its client id and secret.
Instantiate 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.
Username and Password
The Resource Owner Password Credentials Grant is supported with the OAuth2PasswordGrant
subclass.
Create an instance as shown above, set its username
and password
properties, then call authorize()
.
Device Grant
The OAuth 2.0 Device Authorization Grant flow is implemented in the OAuth2DeviceGrant
subclass.
Although 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 to finish the authorization code grant flow.
To 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 to complete the authorization on a secondary device or in the system browser.
Site-Specific Peculiarities
Some sites might not strictly adhere to the OAuth2 flow, from returning data differently like Facebook to omitting mandatory return parameters like Instagram & co. The framework deals with those deviations by creating site-specific subclasses and/or configuration details. If you need to pass additional headers or parameters, you can supply these in the settings dict like so:
let oauth2 = OAuth2CodeGrant(settings: [
"client_id": "...",
...
"headers": ["Accept": "application/vnd.github.v3+json"],
"parameters": ["duration": "permanent"],
] as OAuth2JSON)
Advanced Settings
The main configuration you'll use with oauth2.authConfig
is whether or not to use an embedded login:
oauth2.authConfig.authorizeEmbedded = true
Similarly, if you want to take care of dismissing the login screen yourself (not possible with the newer authorization sessions mentioned below):
oauth2.authConfig.authorizeEmbeddedAutoDismiss = false
Some sites also want the client-id/secret combination in the request body, not in the Authorization header:
oauth2.clientConfig.secretInBody = true
// or in your settings:
"secret_in_body": true
Sometimes you also need to provide additional authorization parameters. This can be done in 3 ways:
oauth2.authParameters = ["duration": "permanent"]
// or in your settings:
"parameters": ["duration": "permanent"]
// or when you authorize manually:
oauth2.authorize(params: ["duration": "permanent"]) { ... }
Similar is how you specify custom HTTP headers:
oauth2.clientConfig.authHeaders = ["Accept": "application/json, text/plain"]
// or in your settings:
"headers": ["Accept": "application/json, text/plain"]
Some 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:
oauth2.customUserAgent = "Version/15.6.1 Safari"
// or in your settings:
"custom_user_agent": "Your string of choice"
Starting with version 2.0.1 on iOS 9, SFSafariViewController
will be used for embedded authorization.
Starting after version 4.2, on iOS 11 (SFAuthenticationSession
) and iOS 12 (ASWebAuthenticationSession
), you can opt-in to these newer authorization session view controllers:
oauth2.authConfig.ui.useAuthenticationSession = true
To revert to the old custom OAuth2WebViewController
, which you should not do because ASWebAuthenticationSession
is way more secure:
oauth2.authConfig.ui.useSafariView = false
To customize the go back button when using OAuth2WebViewController
on iOS 8 and older:
oauth2.authConfig.ui.backButton = <# UIBarButtonItem(...) #>
See below for settings about the keychain and PKCE.
Usage with Alamofire
You'll get the best experience when using Alamofire v4 or newer and OAuth2 v3 and newer:
- How to use Alamofire version 4 and newer
- How to use version 3 and older
Dynamic Client Registration
There is support for dynamic client registration.
If 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.
Client credentials returned from registration are stored to the keychain.
The OAuth2DynReg
class is responsible for handling client registration.
You can use its register(client:callback:)
method manually if you need to.
Registration parameters are taken from the client's configuration.
let oauth2 = OAuth2...()
oauth2.registerClientIfNeeded() { error in
if let error = error {
// registration failed
}
else {
// client was registered
}
}
let oauth2 = OAuth2...()
let dynreg = OAuth2DynReg()
dynreg.register(client: oauth2) { params, error in
if let error = error {
// registration failed
}
else {
// client was registered with `params`
}
}
PKCE
PKCE support is controlled by the useProofKeyForCodeExchange
property, and the use_pkce
key in the settings dictionary.
It is disabled by default. When enabled, a new code verifier string is generated for every authorization request.
Keychain
This framework can transparently use the iOS and macOS keychain.
It is controlled by the useKeychain
property, which can be disabled during initialization with the keychain
settings dictionary key.
Since 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.
If you turn it off after initialization, the keychain will be queried for existing tokens, but new tokens will not be written to the keychain.
If you want to delete the tokens from keychain, i.e. log the user out completely, call forgetTokens()
.
If you have dynamically registered your client and want to start anew, you can call forgetClient()
.
Ideally, access tokens get delivered with an "expires_in" parameter that tells you how long the token is valid.
If it is missing the framework will still use those tokens if one is found in the keychain and not re-perform the OAuth dance.
You will need to intercept 401s and re-authorize if an access token has expired but the framework has still pulled it from the keychain.
This behavior can be turned off by supplying token_assume_unexpired: false
in settings or setting clientConfig.accessTokenAssumeUnexpired
to false.
These are the settings dictionary keys you can use for more control:
keychain
: a bool on whether to use keychain or not, true by defaultkeychain_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.keychain_access_group
: a string value for keychain kSecAttrAccessGroup attribute, nil by defaultkeychain_account_for_client_credentials
: the name to use to identify client credentials in the keychain, "clientCredentials" by defaultkeychain_account_for_tokens
: the name to use to identify the tokens in the keychain, "currentTokens" by default
Installation
You can use the Swift Package Manager, git or Carthage. The preferred way is to use the Swift Package Manager.
Swift Package Manager
In 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.
Carthage
Installation via Carthage is easy enough:
github "p2/OAuth2" ~> 4.2
git
Using Terminal.app, clone the OAuth2 repository, best into a subdirectory of your app project:
$ cd path/to/your/app
$ git clone --recursive https://github.com/p2/OAuth2.git
If you're using git you'll want to add it as a submodule.
Once cloning completes, open your app project in Xcode and add OAuth2.xcodeproj
to your app:
Now link the framework to your app:
These three steps are needed to:
- Make your App also build the framework
- Link the framework into your app
- Embed the framework in your app when distributing
License
This code is released under the Apache 2.0 license, which means that you can use it in open as well as closed source projects.
Since there is no NOTICE
file there is nothing that you have to include in your product.
Top Related Projects
The most scalable and customizable OpenID Certified™ OpenID Connect and OAuth Provider on the market. Become an OpenID Connect and OAuth2 Provider over night. Broad support for related RFCs. Written in Go, cloud native, headless, API-first. Available as a service on Ory Network and for self-hosters.
OpenID Certified™ OAuth 2.0 Authorization Server implementation for Node.js
Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
Open Source Identity and Access Management For Modern Applications and Services
A reverse proxy that provides authentication with Google, Azure, OpenID Connect and many more identity providers.
A spec compliant, secure by default PHP OAuth 2.0 Server
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot