<p>
    OAuth authentication allows users to log in using accounts from other popular services. 
    This can be convenient for users because they can start using your app without creating a new account.
    It can also be more secure, because the user has one less password that could become vulnerable.
</p>

<p>
    When using OAuth to authenticate, the authentication request is initiated from the client application. 
    The user is then redirected to an OAuth 2 provider to complete the authentication step, and finally, the user is redirected back to the client application.
</p>

<h2><a href="#configure" id="configure">Configure OAuth 2 Login</a></h2>
<p>
    Before using OAuth 2 login, you need to enable and configure an OAuth 2 login provider.
</p>

<ol class="margin-top margin-bottom-large text-size-normal">
    <li>Navigate to your Appwrite project.</li>
    <li>Navigate to <b>Auth</b> > <b>Settings</b>.</li>
    <li>Find and open the OAuth provider.</li>
    <li>In the OAuth 2 settings modal, use the toggle to enable the provider.</li>
    <li>Create and OAuth 2 app on the provider's developer platform.</li>
    <li>Copy information from your OAuth2 provider's developer platform to fill the <b>OAuth2 Settings</b> modal in the Appwrite Console.</li>
    <li>Configure redirect URL in your OAuth 2 provider's developer platform. Set it to URL provided to you by <b>OAuth2 Settings</b> modal in Appwrite Console.</li>
</ol>


<h2><a href="#init" id="init">Initialize OAuth 2 Login</a></h2>

<p>
    To initialize the OAuth 2 login process, use the <a href="/docs/client/account#accountCreateOAuth2Session">Create OAuth 2 Session</a> route.
</p>

<ul class="phases clear" data-ui-phases>
    <li>
        <h3>Web</h3>
        <div class="ide" data-lang="javascript" data-lang-label="Web SDK">
        <pre class="line-numbers"><code class="prism language-javascript" data-prism>import { Client, Account } from "appwrite";

const client = new Client()
    .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('[PROJECT_ID]');                 // Your project ID

const account = new Account(client);

// Go to OAuth provider login page
account.createOAuth2Session('amazon', [LINK_ON_SUCCESS], [LINK_ON_FAILURE]);</code></pre>
        </div>
    </li>
    <li>
        <h3>Flutter</h3>
        <div class="ide" data-lang="dart" data-lang-label="Flutter SDK">
            <pre class="line-numbers"><code class="prism language-dart" data-prism>import 'package:appwrite/appwrite.dart';

final client = Client()
    .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('[PROJECT_ID]');               // Your project ID

final account = Account(client);

// Go to OAuth provider login page
await account.createOAuth2Session(provider: 'amazon');</code></pre>
        </div>
    </li>
    <li>
        <h3>Android</h3>
        <p>In order to capture the Appwrite OAuth callback url, the following activity needs to be added inside the <code>&lt;application&gt;</code> tag, along side the existing <code>&lt;activity&gt;</code> tags in your <a href="https://github.com/appwrite/playground-for-android/blob/master/app/src/main/AndroidManifest.xml" target="_blank" rel="noopener">AndroidManifest.xml</a>. Be sure to replace the <code>[PROJECT_ID]</code> string with your actual Appwrite project ID. You can find your Appwrite project ID in your project settings screen in your Appwrite console.</p>

<div class="ide" data-lang="html" data-lang-label="XML">
    <pre class="line-numbers"><code class="prism language-xml" data-prism><?php echo $this->escape('<manifest ...>
  ...
  <application ...>
    ...
    <!-- Add this inside the `<application>` tag, along side the existing `<activity>` tags -->
    <activity android:name="io.appwrite.views.CallbackActivity" android:exported="true">
      <intent-filter android:label="android_web_auth">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="appwrite-callback-[PROJECT_ID]" />
      </intent-filter>
    </activity>
  </application>
</manifest>'); ?>
</code></pre>
</div>
        <div class="ide" data-lang="kotlin" data-lang-label="Android SDK">
            <pre class="line-numbers"><code class="prism language-kotlin" data-prism>import io.appwrite.Client
import io.appwrite.services.Account

val client = Client()
    .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
    .setProject("[PROJECT_ID]")                  // Your project ID

val account = Account(client)

// Go to OAuth provider login page
account.createOAuth2Session(provider = "amazon")</code></pre>
        </div>
    </li>
    <li>
        <h3>Apple</h3>
        <p>In order to capture the Appwrite OAuth callback url, the following URL scheme needs to added to your <code>Info.plist</code>.</p>

<div class="ide" data-lang="html" data-lang-label="XML">
    <pre class="line-numbers"><code class="prism language-xml" data-prism><?php echo $this->escape('<key>CFBundleURLTypes</key>
<array>
<dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLName</key>
    <string>io.appwrite</string>
    <key>CFBundleURLSchemes</key>
    <array>
        <string>appwrite-callback-[PROJECT_ID]</string>
    </array>
</dict>
</array>
');?></code></pre>
</div>

<p>If you're using UIKit, you'll also need to add a hook to your <code>SceneDelegate.swift</code> file to ensure cookies work correctly.</p>

<div class="ide" data-lang="swift" data-lang-label="Swift">
  <pre class="line-numbers"><code class="prism language-swift" data-prism><?php echo $this->escape('
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url,
        url.absoluteString.contains("appwrite-callback") else {
        return
    }
    WebAuthComponent.handleIncomingCookie(from: url)
}
');?></code></pre>
</div>
        <div class="ide" data-lang="swift" data-lang-label="Apple SDK">
            <pre class="line-numbers"><code class="prism language-swift" data-prism>import Appwrite

let client = Client()
    .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
    .setProject("[PROJECT_ID]")                // Your project ID

let account = Account(client)

// Go to OAuth provider login page
try await account.createOAuth2Session(provider: "amazon")</code></pre>
        </div>
    </li>
    <li>
        <h3>GraphQL</h3>
        <div class="notice">
            <p>OAuth 2 is not available through the GraphQL API. You can use the REST API or any Client SDK instead.</p>
        </div>
    </li>
</ul>

<p>
    You'll be redirected to the OAuth 2 provider's login page to log in. 
    Once complete, your user will be redirected back to your app.
</p>

<p>
    You can optionally configure <code>success</code> or <code>failure</code> redirect links on web to handle success and failure scenarios.
</p>

<h2><a href="#profile" id="profile">OAuth 2 Profile</a></h2>
<p>
After authenticating a user through their OAuth 2 provider, you can fetch their profile information such as their avatar image or name. 
To do this you can use the access token from the OAuth 2 provider and make API calls to the provider.
</p>

<p>
After creating an OAuth 2 session, you can fetch the session to get information about the provider.
</p>

<ul class="phases clear" data-ui-phases>
<li>
        <h3>Web</h3>
        <div class="ide" data-lang="javascript" data-lang-label="Web SDK">
            <pre class="line-numbers"><code class="prism language-javascript" data-prism>import { Client, Account } from "appwrite";

const client = new Client();

const account = new Account(client);

const session = await account.getSession('current');

// Provider information
console.log(session.provider);
console.log(session.providerUid);
console.log(session.providerAccessToken);</code></pre>
        </div>
    </li>
    <li>
        <h3>Flutter</h3>
        <div class="ide" data-lang="dart" data-lang-label="Flutter SDK">
            <pre class="line-numbers"><code class="prism language-dart" data-prism>import 'package:appwrite/appwrite.dart';

final client = Client()
    .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('[PROJECT_ID]');               // Your project ID

final account = Account(client);

final session = await getSession(
    sessionId : "[SESSION_ID]"
);

// Provider information
print(session.provider);
print(session.providerUid);
print(session.providerAccessToken);</code></pre>
    </li>
    <li>
        <h3>Android</h3>
        <div class="ide" data-lang="kotlin" data-lang-label="Android SDK">
            <pre class="line-numbers"><code class="prism language-kotlin" data-prism>import io.appwrite.Client
import io.appwrite.services.Account

val client = Client(context)
    .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
    .setProject("5df5acd0d48c2") // Your project ID

val account = Account(client)

val response = account.getSession(
    sessionId = "[SESSION_ID]"
)

// Provider information
print(session.provider);
print(session.providerUid);
print(session.providerAccessToken);</code></pre>
    </li>
    <li>
        <h3>Apple</h3>
        <div class="ide" data-lang="swift" data-lang-label="Apple SDK">
            <pre class="line-numbers"><code class="prism language-swift" data-prism>import Appwrite

let client = Client()
    .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
    .setProject("5df5acd0d48c2") // Your project ID

let account = Account(client)

let session = try await account.getSession(
    sessionId: "[SESSION_ID]"
)

// Provider information
print(session.provider);
print(session.providerUid);
print(session.providerAccessToken);</code></pre>
    </li>
</ul>

<p>
    An OAuth 2 <a href="https://appwrite.io/docs/models/session">session</a> will have the following attributes.
</p>

<table class="full text-size-small">
    <thead>
    <tr>
        <td style="width: 200px">property</td>
        <td>Description</td>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>provider</td>
        <td>The OAuth2 Provider.</td>
    </tr>
    <tr>
        <td>providerUid</td>
        <td> User ID from the OAuth 2 Provider.</td>
    </tr>
    <tr>
        <td>providerAccessToken</td>
        <td>Access token from the OAuth 2 provider. Use this to <b>make requests to the OAuth 2 provider</b> to fetch personal data.</td>
    </tr>
    <tr>
        <td>providerAccessTokenExpiry</td>
        <td>Check this value to know if an access token is about to expire.</td>
    </tr>
    </tbody>
</table>

<p>
    You can use the <code>providerAccessToken</code> to make requests to your OAuth 2 provider.
    Refer to the docs for the OAuth 2 provider you're using to learn about making API calls with the access token.
</p>

<h2><a href="#refresh" id="refresh">Refresh Tokens</a></h2>
<p>
    OAuth 2 sessions expire to protect from security risks. 
    OAuth 2 sessions should be refreshed periodically, so access tokens don't expire. 
    Check value of <code>providerAccessTokenExpiry</code> to know if the token is expired or is about to expire. 
    Refreshing before every request might cause rate limit problems.
    You can do this by calling the <a href="/docs/client/account#accountUpdateSession">Update OAuth Session</a> endpoint when ever your user visits your app.
</p>

<ul class="phases clear" data-ui-phases>
    <li>
        <h3>Web</h3>
        <div class="ide" data-lang="javascript" data-lang-label="Web SDK">
        <pre class="line-numbers"><code class="prism language-javascript" data-prism>const promise = account.updateSession('[SESSION_ID]');

promise.then(function (response) {
    console.log(response); // Success
}, function (error) {
    console.log(error); // Failure
});</code></pre>
        </div>
    </li>
    <li>
        <h3>Flutter</h3>
        <div class="ide" data-lang="dart" data-lang-label="Flutter SDK">
            <pre class="line-numbers"><code class="prism language-dart" data-prism>import 'package:appwrite/appwrite.dart';

final client = Client()
    .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint
    .setProject('5df5acd0d48c2');                // Your project ID

Account account = Account(client);

final result = await account.updateSession(
    sessionId: '[SESSION_ID]'
);</code></pre>
        </div>
    </li>
    <li>
        <h3>Android</h3>
        <div class="ide" data-lang="kotlin" data-lang-label="Android SDK">
            <pre class="line-numbers"><code class="prism language-kotlin" data-prism>import io.appwrite.Client
import io.appwrite.services.Account

val client = Client(context)
    .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
    .setProject("5df5acd0d48c2")                 // Your project ID

val account = Account(client)

val response = account.updateSession(
    sessionId = "[SESSION_ID]"
)</code></pre>
        </div>
    </li>
    <li>
        <h3>Apple</h3>
        <div class="ide" data-lang="swift" data-lang-label="Apple SDK">
            <pre class="line-numbers"><code class="prism language-swift" data-prism>import Appwrite

let client = Client()
    .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint
    .setProject("5df5acd0d48c2") // Your project ID

let account = Account(client)

let session = try await account.updateSession(
    sessionId: "[SESSION_ID]"
)</code></pre>
        </div>
    </li>
    <li>
        <h3>GraphQL</h3>
        <div class="notice">
            <p>OAuth 2 is not available through the GraphQL API. You can use the REST API or any Client SDK instead.</p>
        </div>
    </li>
</ul>