Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 171 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Authgear

Loading...

Get Started

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

How-To Guides

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

User Management

Manage users and their access

Loading...

Loading...

Loading...

Loading...

Single-Page App

You need to protect a JavaScript SPA application that runs entirely in a browser

JavaScript (Web)

Integrate Authgear to your website with the Web SDK

This guide uses the Authgear Web SDK for integrating Authgear with a Web app. Supported browsers include:

  • Last 2 Firefox major versions

  • Last 2 Chrome major versions

  • Last 2 Edge major versions

  • Last 3 Safari major versions

Setup Application in Authgear

From the Project listing, create a new Project or select an existing Project. After that, we will need to create an application in the project.

Install the Authgear Web SDK

NPM

npm install --save --save-exact @authgear/web

Yarn

yarn add @authgear/web --exact

Initialize the Authgear SDK

The SDK must be properly configured before use. Call the configure method every time your page loads up.

import authgear from "@authgear/web";

authgear
  .configure({
    // custom domain endpoint or default endpoint
    // default domain should be something like: https://<yourapp>.authgear.cloud
    endpoint: "<your_app_endpoint>",
    // Client ID of your application
    clientID: "<your_client_id>",
    // sessionType can be "refresh_token" or "cookie", default "refresh_token"
    sessionType: "refresh_token",
  })
  .then(
    () => {
      // configure successfully.
    },
    (err) => {
      // failed to configure.
    }
  );
  
  • Token-based authentication

    • sessionType should be set to refresh_token

  • Cookie-based authentication

    • endpoint must be a custom domain endpoint

    • sessionType should be set to cookie

Login to the application

Step 1: Start the auth flow

When the user clicks login/signup on your website, make a start authorization call to redirect them to the login/signup page.

import authgear from "@authgear/web";

authgear
  .startAuthentication({
    // configure redirectURI which users will be redirected to
    // after they have authenticated with Authgear
    // you can use any path in your website
    // make sure it is in the "Redirect URIs" list of the Application
    redirectURI: "https://yourdomain.com/auth-redirect",
    prompt: "login",
  })
  .then(
    () => {
      // started authorization, user should be redirected to Authgear
    },
    (err) => {
      // failed to start authorization
    }
  );
  

By default, Authgear will not ask user to login again if user has already logged in. You can optionally set prompt to login if you want the user always reach the login page and login again.

Step 2: Handling auth result in the redirectURI

After the user authenticates on the login page, the user will be redirected to the redirectURI with a code parameter in the URL query. In the redirectURI of your application, make a finish authorization call to handle the authentication result. This will attempt to exchange the code for the access token and user info.

Once authorization succeed, the application should navigate the user to other URL such as the user's home page and remove the code query parameters.

import authgear from "@authgear/web";

authgear.finishAuthentication().then(
  (userInfo) => {
    // authorized successfully
    // you should navigate the user to another path
  },
  (err) => {
    // failed to finish authorization
  },
);

Now, your user is logged in!

Get the Logged In State

When you start launching the application. You may want to know if the user has logged in. (e.g. Redirect users to log in if they haven't logged in). The sessionState reflects the user logged in state in the SDK local state. That means even thesessionState is AUTHENTICATED, the session may be invalid if it is revoked remotely. After initializing the Authgear SDK, call fetchUserInfo to update the sessionState as soon as it is proper to do so.

// After authgear.configure, it only reflect SDK local state.
// value can be NO_SESSION or AUTHENTICATED
let sessionState = authgear.sessionState;

if (sessionState === "AUTHENTICATED") {
    authgear
        .fetchUserInfo()
        .then((userInfo) => {
            // sessionState is now up to date
        })
        .catch((e) => {
            // sessionState is now up to date
            // it will change to NO_SESSION if the session is invalid
        });
}

The value of sessionState can be UNKNOWN, NO_SESSION or AUTHENTICATED. Initially the sessionState is UNKNOWN. After a call to authgear.configure, the session state would become AUTHENTICATED if a previous session was found, or NO_SESSION if such session was not found.

Fetching User Info

Log the user out

Use the logout function to log out the user. The user will be redirected to your Authgear endpoint to log out their session. You should provide the redirectURI for the user to return to your app.

import authgear from "@authgear/web";

authgear
  .logout({
    // user will navigate to the redirectURI after logged out
    // make sure it is in the "Post Logout Redirect URIs" in the application portal
    redirectURI: "https://yourdomain.com",
  })
  .then(
    () => {
      // logged out successfully
    },
    (err) => {
      // failed to logout
    }
  );

Calling an API

Token-based authentication

To include the access token to the HTTP requests to your application server, there are two ways to achieve this.

Option 1: Using fetch function provided by Authgear SDK

authgear
    .fetch("YOUR_SERVER_URL")
    .then(response => response.json())
    .then(data => console.log(data));

Option 2: Add the access token to the HTTP request header

You can get the access token through authgear.accessToken. Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of the application request.

authgear
    .refreshAccessTokenIfNeeded()
    .then(() => {
        // access token is ready to use
        // accessToken can be string or undefined
        // it will be empty if user is not logged in or session is invalid
        const accessToken = authgear.accessToken;

        // include Authorization header in your application request
        const headers = {
            Authorization: `Bearer ${accessToken}`
        };
    });

Next steps

JavaScript SDK Reference

In this guide, you'll learn how to integrate Authgear into your website using the . In the token approach, the Authgear server returns an access token and refresh token to your SPA application after successful user authentication. Your application can send this access token in subsequent HTTP requests to access protected resources. The alternative to the token approach is the which involves Authgear setting cookies after successful authentication. Your application will send the cookies in subsequent requests to access protected resources.

Signup for an Authgear Portal account in . Or you can use your self-deployed Authgear.

Step 1: Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application and select the application type Single Page Application or Traditional Web Application. Click "Save".

  4. You will see a list of guides that can help you for setting up, then click "Next".

Step 2: Configure the application

  1. Decide the paths in your website that users will be redirected to after they have authenticated or logged out with Authgear.

    • For after authentication (Authorized Redirect URIs). e.g.https://yourdomain.com/after-authentication , or http://localhost:4000/after-authentication for local development.

    • For after logging out (Post Logout Redirect URIs). e.g.https://yourdomain.com/after-logout , or http://localhost:4000/after-logout for local development.

  2. Fill in the Authorized Redirect URIs and Post Logout Redirect URIs that you have defined in the previous steps.

  3. Click "Save" in the top tool bar and keep the Client ID. You can also obtain it again from the applications list later.

  1. Go to Custom Domains

  2. Add your custom domain in Input New Domain

  3. Follow the instructions to verify and configure the custom domain.

  4. Click "Activate" to change the domain status to "Active". The custom domain will be your new Authgear endpoint.

For cookie-based authentication, users will log in via the custom domain e.g. "auth.yourdomain.com" . So that a session cookie of your domain is set for the client and all your websites under "*.yourdomain.com" would share the same session cookies automatically.

oauth:
  clients:
    - name: mywebsite
      client_id: a_random_generated_string
      redirect_uris:
        - "https://yourdomain.com/auth-redirect"
      post_logout_redirect_uris:
        - "https://yourdomain.com/after-logout"
      grant_types:
        - authorization_code
        - refresh_token
      response_types:
        - code
        - none

The Web JS SDK is available as . Install the package in your project directory

The SDK should be according to the authentication approach of your choice

In some cases, you may need to obtain current user info through the SDK. (e.g. Display email address in the UI). Use the fetchUserInfo function to obtain the user info, see .

Authgear SDK provides the fetch function for you to call your application server. This fetch function will include the Authorization header in your application request, and handle refresh access token automatically. The authgear.fetch implements .

To protect your application server from unauthorized access. You will need to .

For detailed documentation on the JavaScript Web SDK, visit

If you want to validate JWT access token in your server, under Access Token, turn on Issue JWT as access token. If you will forward incoming requests to Authgear Resolver Endpoint for authentication, leave this unchecked. See comparisons in .

Step 3: Setup a custom domain (Required for )

Angular
JavaScript (Web)
React
Vue
Token Approach
Cookies Approach
https://portal.authgear.com/
Backend Integration
Cookie-based authentication
an npm package
configured
fetch
integrate Authgear to your backend
Backend Integration
@authgear/web Reference

Start Building

Choose your application type for a getting-started guide

Single Page Application

Step-by-step guide for JavaScript applications that run in the browser.

Native/Mobile Apps

Step-by-step guide on how to use Authgear to add user authentication to your mobile application.

Regular Web App

Guides for using Authgear in web applications that run on the server side.

Create an application
Edit an application

Android OKHttp Interceptor Extension (Optional)

The Authgear Android SDK provides an optional Okhttp interceptor which handles everything from refreshing the access token to putting the access token in the header.

Get the Extension

The extension is included in the SDK. Please refer to the above section for getting the SDK.

Usage

Configure OkHttpClient to use AuthgearInterceptor as follows:

Authgear authgear = // Obtain the authgear instance.
OKHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(AuthgearInterceptor(authgear))
            .build()

The client would then include the access token in every request and refresh the access token when necessary before the requests.

Authgear Overview

Authgear is a highly adaptable identity-as-a-service (IDaaS) platform for web and mobile applications

Authgear is an authentication & user management solution which makes it very easy for developers to integrate and customize their consumer applications, it includes these features out of the box:

  • Easy-to-use interfaces for user registration and login, including email, phone, username as login ID, and password, OTP, magic links, etc for authentication.

  • Support biometric login on mobile, Passkeys, and Multi-Factor Authentication (MFA) such as SMS/email-based verification and authenticator apps with TOTP.

  • A user management portal, like password resets, account locking, scheduled deletion or anonymization, and user profile management.

  • Single Sign-On (SSO) provides a single unified experience for your customers to log into multiple web/mobile apps, including Web2Web, Web2App, and App2App SSO.

  • Session management with Authgear Portals, and a pre-built setting page for users to control concurrent sessions.

  • Customizable UI with a user-friendly low-code dashboard.

  • Various security features such as audit logs, brute force protection, smart account lockout, password policy, etc.

Learn about Authgear

Authgear contains the following high-level components:

Authenticate on the Web/Mobile App

  • Auth UI - is the default batteries included UI for login, signup and setting page. You can customize the style via the Portal, including the CSS and HTML of each page.

Backend Authentication and Integrations

Management Portal

Security

Login Methods

Customize User Interface (UI)

User Management

Features for managing your users via Authgear Portal.

Zero trust authentication architecture with (OIDC) standard.

Support a wide range of identity providers, such as , , and (AD).

APIs for further integration and customizations. For example, build your own custom login and sign-up pages from the ground up powered by .

Most importantly, you can with Authgear for free.

Client App SDKs - for developers to quickly implement authentication with Auth UI on your web and mobile applications. Check out for tutorials and API References.

- for developers to implement their own login, signup and reauthenticate UI (e.g. a mobile native view); or to define a customized login, signup and reauth flow.

- for developers to use Authgear with other software that already support OIDC login, you can use Authgear as an OpenID Connect Provider.

- explain the common approach of using Access Token or Cookies (JWT or random string) to authenticate an API or HTTP Requests.

- allow your backend to interact directly with Authgear for user management purpose.

- call external web endpoint or use the hosted type-script to customize the behaviour of Authgear. E.g. blocking certain type of sign up, or call external endpoint for each login.

- Import multiple users from another service to your project.

- Export user data from Authgear into a CSV or file.

- Link an OAuth provider to a user's account without AuthUI.

Authgear Portal - You can configure your projects, manage users, check out , or customize the AuthUI. See the for Authgear Portal.

Analytics Page - View reports of all users and active users over a specific time interval on the .

- Set account Lockout Policy to safeguard a user account from brute-force login attempts.

- Bot protection tools to block automated attackers.

- Learn how to set password strength and how the password strength is calculated.

- Add biometric login to your application.

- Enable 2FA in your Authgear project.

- Allow users to log in without a password using a magic link.

- Set up passkey for your project.

- Allow users to log in to your application using their existing account with a social media site or enterprise login provider.

- Customize the look and feel of AuthUI to match your branding.

- Change the language for display texts.

- Create a new account for a user from Authgear Portal.

- Delete a user account from your project.

- Detailed guide on how to use Roles and Groups.

- Guides on how to view and manage user profile information.

OpenID Connect
Google
Apple
Azure Active Directory
Authentication Flow API
get started
Start Building
Authentication Flow API
Use Authgear as OpenID Connect Provider
Backend Integration
Admin API
Events and Hooks
User Import API
Export User API
ndjosn
Link OAuth Provider using Account Management API
audit log
5-minute quick start guide
analytics page
Brute-force Protection
Bot Protection
Password Strength
Biometric Login
Two-Factor Authentication (2FA)
Email Magic Link Login
Passkeys Login
Social Login / Enterprise Login
Customize Built-in UI
Language and Localization
Create a new account on behalf of a user
Account Deletion
User Roles and Groups
User Profiles

Get Started

Jump in with Authgear's getting started guides.

How-To Guides

Find a step-by-step guide to take your project to the next level.

Concepts

Learn the basics.

Cover

React

Cover

JavaScript (Web)

Cover

Angular

Cover

Vue

Cover

Android

Cover

iOS

Cover

React Native

Cover

Flutter

Cover

Ionic

Cover

Xamarin

Cover

Java (Spring Boot)

Cover

Express

Cover

Laravel

Cover

Next.js

Cover

PHP

Cover

Python (Flask App)

Cover

ASP.NET Core MVC

5-Minute Guide

A quick guide on getting started with Authgear

Authgear makes it easy to add user authentication and authorization to any application. In this guide, we'll show you how to get started with Authgear in 5 minutes.

Video Guide

1. Create Authgear account

After you sign up, you'll see the onboarding screen that will guide you through the process of creating your first Authgear project.

2. Authgear Projects

An Authgear project is similar to a container that holds all your users, settings, and client applications. You need an Authgear project before you can start signing users up.

You can create multiple projects under one account based on your needs. When you create multiple projects, each project is isolated from the others. For example, you can create Project 1 for your e-commerce business and Project 2 for a fitness club you organize. Project 1 and Project 2 will not share the same users or settings.

To create an additional project, log in to your Authgear account then click on the Create Project button.

3. Testing your signup/login page

Before any integration, you can try out the signup flow for your project from the "Getting Started" page.

You should be greeted with the AuthUI Login/Sign-up page. Use the form to create a new user account under your project.

The flow for sign-up and login will differ based on the login method you enable for your Authgear project. For example, users can sign up using their phone number and password if you enable the Mobile login method.

4. User Settings Page

After logging in from the previous step, you can check out the Pre-Built User Settings Page. This page is the default page where users of your project can edit their profile and manage security settings.

Click on the More link under My profile to view and edit profile attributes such as first name, last name, photo, etc.

The Security section of the User Settings page has the following options:

  • Password: users can change their password from here.

  • 2-step verification: users can click on this option to view and manage 2-step authenticators for their account.

  • Signed-in device: from this page, the user can view browsers and devices that their account is currently signed in on.

5. Integrate Authgear with Your Application or Website

To get more from Authgear and use Authgear to add user authentication to your web or mobile application, you should integrate Authgear to your application or website.

6. View and Manage Your Users

Authgear offers multiple options for viewing and managing all users who sign up for your project. These options include:

  • Authgear Portal

The quickest way to manage your users is from the Authgear Portal. To open the user management page in the Authgear Portal, click on the User Management link in the navigation bar on the left side.

Click on Users to view a list of all the users in your project. Click on a user from the list to view their complete profile and perform administrative operations like modify profile details, suspend/unsuspend user, delete account, etc.

You can also add new users to your project from the User Management page. To do that, click on the Create User button on the right.

7. Continue Exploring Authgear

Continue to navigate around the Authgear Portal to see all the features and settings available for your project.

You can also check out any of the following guides to learn more about Authgear:

Angular

Follow this quickstart tutorial to add authentication to your Angular application

Authgear helps you add user logins to your Angular apps. It provides prebuilt login page and user settings page that accelerate the development.

Table of Content

Setup Application in Authgear

After that, we will need to create an Application in the Project Portal.

Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application, e.g. "MyAwesomeApp".

  4. Select Single Page Application as the application type

  5. Click "Save" to create the application

Configure Authorize Redirect URI

The Redirect URI is a URL in you application where the user will be redirected to after login with Authgear. In this path, make a finish authentication call to complete the login process.

For this tutorial, add http://localhost:4000/auth-redirect to Authorize Redirect URIs.

Configure Post Logout Redirect URI

The Post Logout Redirect URI is the URL users will be redirected after they have logged out. The URL must be whitelisted.

For this tutorial, add http://localhost:4000/ to Post Logout Redirect URIs.

Save the configuration before next steps.

Step 1: Create a simple Angular project

Here are some recommended steps to scaffold an Angular project. You can skip this part if you are adding Authgear to an existing project. See Step 2: Install Authgear SDK to the project in the next section.

Install the Angular CLI

To install the Angular CLI, open a terminal window and run the following command:

npm install -g @angular/cli

Create initial workspace

Run the following cli command to create a new workspace and initial app called my-app with a routing module generated.

# Create a workspace called my-app
ng new my-app --routing --defaults
# Move into the project directory
cd my-app

Edit script for launching the app

In the package.json file, edit the start script in the script section

# before
"start": "ng serve"

# after
"start": "ng serve --port 4000"

The start script run the app in development mode on port 4000 instead of the default one.

Edit the app.component.html file

By default, the Angular CLI generated an initial application for us, but for simplicity, we recommend to modify some of these files to scratch.

In the src/app/app.component.html file, remove all the lines and add the following line:

<div>Hello world</div>

Run your initial app

Run npm start now to run the project and you will see "Hello world" on http://localhost:4000.

Step 2: Install Authgear SDK to the project

Run the following command within your Angular project directory to install the Authgear Web SDK

npm install --save-exact @authgear/web

In src/app/app.component.ts , import authgear and call the configure function to initialize an Authgear instance on application loads.

// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import authgear from '@authgear/web';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
  // configure Authgear container instance
  initAuthgear(): Promise<void> {
    return authgear.configure({
      endpoint: '<your_app_endpoint>',
      clientID: '<your_client_id>',
      sessionType: 'refresh_token',
    });
  }

  ngOnInit(): void {
    this.initAuthgear().catch((e) => {
      // Error handling
      console.log(e);
    });
  }
}

The Authgear container instance takes endpoint and clientID as parameters. They can be obtained from the application page created in Setup Application in Authgear.

It is recommend to render the app after configure() resolves. So by the time the app is rendered, Authgear is ready to use.

Run npm start now and you should see a page with "Hello World" and no error message in the console if Authgear SDK is configured successfully

Step 3: Implement the User Service

Since we want to reference the logged in state in anywhere of the app, let's put the state in a service with user.service.ts in the /src/app/services/ folder.

In user.service.ts, it will have a isLoggedIn boolean variable. The isLoggedIn boolean variable can be auto updated using the onSessionStateChange callback. This callback can be stored in delegate which is in the local SDK container.

// src/app/services/user.service.ts
import { Injectable } from '@angular/core';
import authgear from '@authgear/web';

@Injectable({
  providedIn: 'root',
})
export class UserService {
  // By default the user is not logged in
  isLoggedIn: boolean = false;

  constructor() {
    // When the sessionState changed, logged in state will also be changed
    authgear.delegate = {
      onSessionStateChange: (container) => {
        // sessionState is now up to date
        // value of sessionState can be "NO_SESSION" or "AUTHENTICATED"
        const sessionState = container.sessionState;
        if (sessionState === 'AUTHENTICATED') {
          this.isLoggedIn = true;
        } else {
          this.isLoggedIn = false;
        }
      },
    };
  }
}

Step 4: Implement the Auth Redirect

Next, we will add an "auth-redirect" page for handling the authentication result after the user have been authenticated by Authgear.

Create the auth-redirect component using the following command:

ng generate component auth-redirect

We will inject the router and the UserService to get the use of navigation and the isLoggedIn state.

Call the Authgear finishAuthentication() function in the Auth Redirect component to send a token back to Authgear server in exchange for access token and refresh token. Don't worry about the technical jargons, finishAuthentication() will do all the hard work for you and and save the authentication data.

When the authentication is finished, the isLoggedIn state from the UserService will automatic set to true. Finally, navigate back to root (/) which is our Home page.

The final auth-redirect.component.ts will look like this

// src/app/auth-redirect/auth-redirect.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
import authgear from '@authgear/web';
import { Router } from '@angular/router';

@Component({
  selector: 'app-auth-redirect',
  templateUrl: './auth-redirect.component.html',
  styleUrls: ['./auth-redirect.component.css'],
})
export class AuthRedirectComponent implements OnInit {
  constructor(private router: Router, private user: UserService) {}

  ngOnInit(): void {
    authgear
      .finishAuthentication()
      .catch((e) => console.error(e))
      .then(() => {
        this.router.navigate(['']);
      });
  }
}

Step 5: Add Routes and Context Provider to the App

Next, we will add a "Home" page . Create a home component using the following command:

ng generate component home

Then import HomeComponent and AuthRedirectComponent as routes. We can add those routes in the app-routing.module.ts file:

// src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthRedirectComponent } from './auth-redirect/auth-redirect.component';
import { HomeComponent } from './home/home.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'auth-redirect', component: AuthRedirectComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

You can apply those routes in src/app/app.component.html by replace the lines with the following:

<router-outlet></router-outlet>

The file structure should now look like

src
├── (...)
└── app
    ├── app-routing.module.ts
    ├── app.component.ts
    ├── app.component.html
    ├── app.module.ts
    ├── (...)
    ├── auth-redirect
    │   ├── auth-redirect.component.ts
    │   ├── auth-redirect.component.html
    │   └── (...)
    ├── home
    │   ├── home.component.ts
    │   ├── home.component.html
    │   └── (...)
    └── services
        └── user.service.ts

Step 6: Add a Login button

First we will import the Authgear dependency and inject the UserService in home.component.ts. Then add the startLogin method which will call startAuthentication(ConfigureOptions). This will redirect the user to the login page.

// src/app/home/home.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
import authgear from '@authgear/web';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  constructor(public user: UserService) {}

  ngOnInit(): void {}

  startLogin(): void {
    authgear
      .startAuthentication({
        redirectURI: 'http://localhost:4000/auth-redirect',
        prompt: 'login',
      })
      .then(
        () => {
          // started authorization, user should be redirected to Authgear
        },
        (err) => {
          // failed to start authorization
          console.error(err);
        }
      );
  }
}

Then you can add a button which will trigger the startLogin method in home.component.html:

<h1>Home Page</h1>
<button type="button" (click)="startLogin()">Login</button>

You can now run npm start and you will be redirected to the Authgear Login page when you click the Login button.

Step 7: Show the user information

The Authgear SDK helps you get the information of the logged in users easily.

In the last step, the user is successfully logged in so let's try to print the user ID (sub) of the user in the Home page.

In home component, we will add a simple Loading splash and a greeting message printing the Sub ID. We will add two conditional elements such that they are only shown when user is logged in. We can also change the login button to show only if the user is not logged in.

Make use of isLoggedIn from the UserService to control the components on the page. Fetch the user info by fetchInfo() and access its sub property.

// src/app/home/home.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
import authgear from '@authgear/web';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  isLoading: boolean = false;
  greetingMessage: string = '';

  constructor(public user: UserService) {}

  async updateGreetingMessage() {
    this.isLoading = true;
    try {
      if (this.user.isLoggedIn) {
        const userInfo = await authgear.fetchUserInfo();
        this.greetingMessage = 'The current User sub: ' + userInfo.sub;
      }
    } finally {
      this.isLoading = false;
    }
  }

  ngOnInit(): void {
    this.updateGreetingMessage().catch((e) => {
      console.error(e);
    });
  }

  startLogin(): void {
    authgear
      .startAuthentication({
        redirectURI: 'http://localhost:4000/auth-redirect',
        prompt: 'login',
      })
      .then(
        () => {
          // started authorization, user should be redirected to Authgear
        },
        (err) => {
          // failed to start authorization
          console.error(err);
        }
      );
  }
}

In the home.component.html:

<h1>Home Page</h1>
<span *ngIf="isLoading">Loading</span>
<span *ngIf="greetingMessage">{{ greetingMessage }}</span>
<div *ngIf="!user.isLoggedIn">
  <button type="button" (click)="startLogin()">Login</button>
</div>

Run the app again, the User ID (sub) of the user should be printed on the Home page.

Step 8: Add a Logout button

Finally, let's add an Logout button when user is logged in.

In home.component.html, we will add a conditional element in the markup:

<div *ngIf="user.isLoggedIn">
  <button type="button" (click)="logout()">Logout</button>
</div>

And add the logout method:

logout(): void {
  authgear
    .logout({
      redirectURI: 'http://localhost:4000/',
    })
    .then(
      () => {
        this.greetingMessage = '';
      },
      (err) => {
        console.error(err);
      }
    );
}

Run the app again, we can now logout by clicking the logout button.

Step 9: Open User Settings

Authgear provide a built-in UI for the users to set their attributes and change security settings.

Use the open function to open the setting page at <your_app_endpoint>/settings

In home.component.html append a conditional link to the logout button section.

<div *ngIf="user.isLoggedIn">
  <button type="button" (click)="logout()">Logout</button>
  <br />
  <a target="_blank" rel="noreferrer" (click)="userSetting($event)" href="#">
    User Setting
  </a>
</div>

And add the userSetting method:

import authgear, { Page } from "@authgear/web";

async userSetting(event: MouseEvent) {
  event.preventDefault();
  event.stopPropagation();
  await authgear.open(Page.Settings);
}

This the resulting home.component.ts:

// src/app/home/home.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user.service';
import authgear, { Page } from '@authgear/web';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  isLoading: boolean = false;
  greetingMessage: string = '';

  constructor(public user: UserService) {}

  async updateGreetingMessage() {
    this.isLoading = true;
    try {
      if (this.user.isLoggedIn) {
        const userInfo = await authgear.fetchUserInfo();
        this.greetingMessage = 'The current User sub: ' + userInfo.sub;
      }
    } finally {
      this.isLoading = false;
    }
  }

  ngOnInit(): void {
    this.updateGreetingMessage().catch((e) => {
      console.error(e);
    });
  }

  startLogin(): void {
    authgear
      .startAuthentication({
        redirectURI: 'http://localhost:4000/auth-redirect',
        prompt: 'login',
      })
      .then(
        () => {
          // started authorization, user should be redirected to Authgear
        },
        (err) => {
          // failed to start authorization
          console.error(err);
        }
      );
  }

  logout(): void {
    authgear
      .logout({
        redirectURI: 'http://localhost:4000/',
      })
      .then(
        () => {
          this.greetingMessage = '';
        },
        (err) => {
          console.error(err);
        }
      );
  }

  async userSetting(event: MouseEvent) {
    event.preventDefault();
    event.stopPropagation();
    await authgear.open(Page.Settings);
  }
}

This is the resulting home.component.html:

<h1>Home Page</h1>
<span *ngIf="isLoading">Loading</span>
<span *ngIf="greetingMessage">{{ greetingMessage }}</span>
<div *ngIf="!user.isLoggedIn">
  <button type="button" (click)="startLogin()">Login</button>
</div>
<div *ngIf="user.isLoggedIn">
  <button type="button" (click)="logout()">Logout</button>
  <br />
  <a target="_blank" rel="noreferrer" (click)="userSetting($event)" href="#">
    User Setting
  </a>
</div>

Next steps, Calling an API

To access restricted resources on your backend application server, the HTTP requests should include the access token in their Authorization headers. The Web SDK provides a fetch function which automatically handle this, or you can get the token with authgear.accessToken.

Option 1: Using fetch function provided by Authgear SDK

authgear
    .fetch("YOUR_SERVER_URL")
    .then(response => response.json())
    .then(data => console.log(data));

Option 2: Add the access token to the HTTP request header

You can get the access token through authgear.accessToken. Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of the application request.

authgear
    .refreshAccessTokenIfNeeded()
    .then(() => {
        // access token is ready to use
        // accessToken can be string or undefined
        // it will be empty if user is not logged in or session is invalid
        const accessToken = authgear.accessToken;

        // include Authorization header in your application request
        const headers = {
            Authorization: `Bearer ${accessToken}`
        };
    });

Vue

Follow this quickstart tutorial to add authentication to your Vue application

Authgear helps you add user logins to your Vue apps. It provides prebuilt login page and user settings page that accelerate the development.

Table of Content

Setup Application in Authgear

After that, we will need to create an Application in the Project Portal.

Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application, e.g. "MyAwesomeApp".

  4. Select Single Page Application as the application type

  5. Click "Save" to create the application

Configure Authorize Redirect URI

The Redirect URI is a URL in you application where the user will be redirected to after login with Authgear. In this path, make a finish authentication call to complete the login process.

For this tutorial, add http://localhost:4000/auth-redirect to Authorize Redirect URIs.

Configure Post Logout Redirect URI

The Post Logout Redirect URI is the URL users will be redirected after they have logged out. The URL must be whitelisted.

For this tutorial, add http://localhost:4000/ to Post Logout Redirect URIs.

Save the configuration before next steps.

Step 1: Create a simple Vue project

Here are some recommended steps to scaffold a Vue project. You can skip this part if you are adding Authgear to an existing project. See Step 3: Install Authgear SDK to the project in the next section.

Install basic project dependencies

Create the project folder and install the dependencies. We will use vite as the build tool and the vue-router package. Also, we will use TypeScript in this tutorial.

# Create a brand new project using vite
npm create vite@latest my-app -- --template vue-ts
# Move into the project directory
cd my-app
# Install dependencies
npm install
# Install vue-router
npm install --save-exact vue-router

Add port configuration for development mode

As we are using port 4000 for this tutorial, we need to add the port information to the config. In the vite.config.ts file, modify the file with the following lines:

// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    port: 4000,
  },
});

After doing so, when you run npm run dev , the server will be running on port 4000.

Create the Home.vue file

Create a new file called Home.vue in the src/components folder with simply showing Hello World on the screen.

// src/components/Home.vue
<script setup lang="ts"></script>

<template><div>Hello World</div></template>

Edit the App.vue file

The App.vue file is generated by Vite already but some sections might not being needed for this tutorial.

// src/components/App.vue
<script setup lang="ts">
import Home from "./components/Home.vue";
</script>

<template>
  <Home />
</template>

Delete unnecessary files

Some of the files might not being used and thus can be deleted. You can perform the following script to delete these files:

rm -rf src/assets src/components/HelloWorld.vue

File structure

The file structure in your project is now:

my-app
├── node_modules
│   └── (...)
├── package-lock.json
├── package.json
├── vite.config.ts
├── (...)
└── src
    ├── components
    │   └── Home.vue
    ├── App.vue
    ├── main.ts
    └── (...)

Run npm run dev now to run the project and you will see default page with the title Vite + Vue and a count button on http://localhost:4000.

Step 2: Create routes for the project

Create a AuthRedirect.vue file in the src/components folder with the same content as src/components/Home.vue at this moment.

Create a file called router.ts in the src/ folder. We will import Home and AuthRedirect component as the route and we will implement these components later. The content of this file will look like this:

// src/router.ts
import { createRouter, createWebHistory } from "vue-router";

export const history = createWebHistory();
export const router = createRouter({
  history,
  routes: [
    {
      path: "/",
      // We will implement this component later
      component: () => import("./components/Home.vue"),
    },
    {
      path: "/auth-redirect",
      // We will implement this component later
      component: () => import("./components/AuthRedirect.vue"),
    },
  ],
});

Step 3: Install Authgear SDK to the project

Run the following command within your Vue project directory to install the Authgear Web SDK

npm install --save-exact @authgear/web

In src/main.ts , import authgear and call the configure function to initialize an Authgear instance on application loads. We will also import router and use it to build routes for us.

// src/main.ts
import { createApp } from "vue";
import './style.css'
import App from "./App.vue";
import { router } from "./router";
import authgear from "@authgear/web";

const app = createApp(App);

async function init() {
  try {
    // configure Authgear container instance
    await authgear.configure({
      endpoint: "<your_app_endpoint>",
      clientID: "<your_client_id>",
      sessionType: "refresh_token",
    });
  } finally {
    app.use(router);
    app.mount("#app");
  }
}

init().catch((e) => {
  // Error handling
  console.error(e)
});

The Authgear container instance takes endpoint and clientID as parameters. They can be obtained from the application page created in Setup Application in Authgear.

It is recommend to render the app after configure() resolves. So by the time the app is rendered, Authgear is ready to use.

Run npm run dev now and you should see the same page and no error message in the console if Authgear SDK is configured successfully

Step 4: Implement the Context Provider

Since we want to reference the logged in state in anywhere of the app, let's put the state in a context provider with UserProvider.vue in the /src/contexts folder.

In UserProvider.vue, it will have a isLoggedIn boolean value. The isLoggedIn boolean state can be auto updated using the onSessionStateChange callback. This callback can be stored in delegate which is in the local SDK container.

// src/context/UserProvider.vue
<script lang="ts">
import {
  defineComponent,
  InjectionKey,
  provide,
  readonly,
  ref,
  Ref,
  toRefs,
} from "vue";
import authgear from "@authgear/web";

export interface UserContextValue {
  isLoggedIn: Ref<boolean>;
}

export const UserStateSymbol: InjectionKey<UserContextValue> =
  Symbol("UserState");

export default defineComponent({
  setup() {
    const isLoggedIn = ref(false);

    const state: UserContextValue = {
      isLoggedIn,
    };

    authgear.delegate = {
      onSessionStateChange: (container) => {
        const sessionState = container.sessionState;
        if (sessionState === "AUTHENTICATED") {
          isLoggedIn.value = true;
        } else {
          isLoggedIn.value = false;
        }
      },
    };

    provide<UserContextValue>(UserStateSymbol, toRefs(readonly(state)));

    return { state };
  },
});
</script>

<template>
  <slot />
</template>

Step 5: Implement the Auth Redirect

Next, we will add an "AuthRedirect" page for handling the authentication result after the user have been authenticated by Authgear.

Create the AuthRedirect.vue component file in the src/components/ folder.

Call the Authgear finishAuthentication() function in the Auth Redirect component to send a token back to Authgear server in exchange for access token and refresh token. Don't worry about the technical jargons, finishAuthentication() will do all the hard work for you and and save the authentication data.

When the authentication is finished, the isLoggedIn state from the UserContextProvider will automatic set to true. Finally, navigate back to root (/) which is our Home page.

The final AuthRedirect.vue will look like this

// src/components/AuthRedirect.vue
<script setup lang="ts">
import { onMounted } from "vue";
import authgear from "@authgear/web";
import { router } from "../router";

onMounted(() => {
  async function updateToken() {
    try {
      await authgear.finishAuthentication();
    } finally {
      router.replace({ path: "/" });
    }
  }
  updateToken().catch((e) => console.error(e));
});
</script>

<template></template>

Step 6: Apply Routes and Context Provider to the App

As we have already configure the routes in the previous section, we can simply add <router-view /> tag to the App.vue. We can then Import UserProvider and wrap the router-view with it.

Your final App.vue should look like this:

// src/App.vue
<script setup lang="ts">
import UserProvider from "./contexts/UserProvider.vue";
</script>

<template>
  <UserProvider>
    <router-view />
  </UserProvider>
</template>

The file structure should now look like

src
├── App.vue
├── main.ts
├── router.ts
├── vite-env.d.ts
├── contexts
│   └── UserProvider.vue
└── components
    ├── AuthRedirect.vue
    └── Home.vue

Step 7: Add a Login button

First we will import the Authgear dependency. Then add the login button which will call startAuthentication(ConfigureOptions) through startLogin callback on click. This will redirect the user to the login page.

// src/components/Home.vue
<script setup lang="ts">
import authgear from "@authgear/web";

const startLogin = () => {
  authgear
    .startAuthentication({
      redirectURI: "http://localhost:4000/auth-redirect",
      prompt: "login",
    })
    .then(
      () => {
        // started authorization, user should be redirected to Authgear
      },
      (err) => {
        // failed to start authorization
        console.error(err);
      }
    );
};
</script>

<template>
  <h1>Home Page</h1>
  <button @click="startLogin">Login</button>
</template>

You can now run npm run dev and you will be redirected to the Authgear Login page when you click the Login button.

Step 8: Show the user information

The Authgear SDK helps you get the information of the logged in users easily.

In the last step, the user is successfully logged in so let's try to print the user ID (sub) of the user in the Home page.

In Home.vue, we will add a simple Loading splash and a greeting message printing the Sub ID. We will add two conditional elements such that they are only shown when user is logged in. We can also change the login button to show only if the user is not logged in.

Make use of isLoggedIn from the UserProvider to control the components on the page. Fetch the user info by fetchInfo() and access its sub property.

The Login button can be also rendered conditionally which only visible if the user is not logged in.

// src/components/Home.vue  
<script setup lang="ts">
import authgear from "@authgear/web";
import { inject, onMounted, ref } from "vue";
import { UserStateSymbol } from "../contexts/UserProvider.vue";

const { isLoggedIn } = inject(UserStateSymbol)!;
const isLoading = ref(false);
const greetingMessage = ref("");

onMounted(() => {
  async function updateGreetingMessage() {
    isLoading.value = true;
    try {
      if (isLoggedIn.value) {
        const userInfo = await authgear.fetchUserInfo();
        greetingMessage.value = "The current User sub: " + userInfo.sub;
      }
    } finally {
      isLoading.value = false;
    }
  }

  updateGreetingMessage().catch((e) => {
    console.error(e);
  });
});

const startLogin = () => {
  authgear
    .startAuthentication({
      redirectURI: "http://localhost:4000/auth-redirect",
      prompt: "login",
    })
    .then(
      () => {
        // started authorization, user should be redirected to Authgear
      },
      (err) => {
        // failed to start authorization
        console.error(err);
      }
    );
};
</script>

<template>
  <h1>Home Page</h1>
  <span v-if="isLoading">Loading...</span>
  <span v-if="greetingMessage">{{ greetingMessage }}</span>
  <div v-if="!isLoggedIn">
    <button @click="startLogin">Login</button>
  </div>
</template>

Run the app again, the User ID (sub) of the user should be printed on the Home page.

Step 9: Add a Logout button

Finally, let's add an Logout button when user is logged in.

In Home.vue, we will add a conditional elements in the template:

<div v-if="isLoggedIn">
  <button @click="logout">Logout</button>
</div>

And add the logout callback:

const logout = () => {
  authgear
    .logout({
      redirectURI: "http://localhost:4000/",
    })
    .then(
      () => {
        greetingMessage.value = "";
      },
      (err) => {
        console.error(err);
      }
    );
};

Run the app again, we can now logout by clicking the logout button.

Step 10: Open User Settings

Authgear provide a built-in UI for the users to set their attributes and change security settings.

Use the open function to open the setting page at <your_app_endpoint>/settings

In Home.vue append a conditional link to the logout button section.

<div v-if="isLoggedIn">
  <button @click="logout()">Logout</button>
  <br />
  <a
    target="_blank"
    rel="noreferrer"
    @click.stop.prevent="userSetting"
    href="#"
  >
    User Setting
  </a>
</div>

And add the userSetting callback:

import authgear, { Page } from "@authgear/web";

const userSetting = async () => {
  await authgear.open(Page.Settings);
};

This the the resulting Home.vue:

// src/components/Home.vue
<script setup lang="ts">
import authgear, { Page } from "@authgear/web";
import { inject, onMounted, ref } from "vue";
import { UserStateSymbol } from "../contexts/UserProvider.vue";

const { isLoggedIn } = inject(UserStateSymbol)!;
const isLoading = ref(false);
const greetingMessage = ref("");

onMounted(() => {
  async function updateGreetingMessage() {
    isLoading.value = true;
    try {
      if (isLoggedIn.value) {
        const userInfo = await authgear.fetchUserInfo();
        greetingMessage.value = "The current User sub: " + userInfo.sub;
      }
    } finally {
      isLoading.value = false;
    }
  }

  updateGreetingMessage().catch((e) => {
    console.error(e);
  });
});

const startLogin = () => {
  authgear
    .startAuthentication({
      redirectURI: "http://localhost:4000/auth-redirect",
      prompt: "login",
    })
    .then(
      () => {
        // started authorization, user should be redirected to Authgear
      },
      (err) => {
        // failed to start authorization
        console.error(err);
      }
    );
};

const logout = () => {
  authgear
    .logout({
      redirectURI: "http://localhost:4000/",
    })
    .then(
      () => {
        greetingMessage.value = "";
      },
      (err) => {
        console.error(err);
      }
    );
};

const userSetting = async () => {
  await authgear.open(Page.Settings);
};
</script>

<template>
  <h1>Home Page</h1>
  <span v-if="isLoading">Loading...</span>
  <span v-if="greetingMessage">{{ greetingMessage }}</span>
  <div v-if="!isLoggedIn">
    <button @click="startLogin">Login</button>
  </div>
  <div v-if="isLoggedIn">
    <button @click="logout">Logout</button>
    <br />
    <a
      target="_blank"
      rel="noreferrer"
      @click.stop.prevent="userSetting"
      href="#"
    >
      User Setting
    </a>
  </div>
</template>

Next steps, Calling an API

To access restricted resources on your backend application server, the HTTP requests should include the access token in their Authorization headers. The Web SDK provides a fetch function which automatically handle this, or you can get the token with authgear.accessToken.

Option 1: Using fetch function provided by Authgear SDK

authgear
    .fetch("YOUR_SERVER_URL")
    .then(response => response.json())
    .then(data => console.log(data));

Option 2: Add the access token to the HTTP request header

You can get the access token through authgear.accessToken. Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of the application request.

authgear
    .refreshAccessTokenIfNeeded()
    .then(() => {
        // access token is ready to use
        // accessToken can be string or undefined
        // it will be empty if user is not logged in or session is invalid
        const accessToken = authgear.accessToken;

        // include Authorization header in your application request
        const headers = {
            Authorization: `Bearer ${accessToken}`
        };
    });

React Native SDK

How to integrate with a React Native app

This guide provides instructions on integrating Authgear with a React Native app. Supported platforms include:

  • React Native 0.60.0 or higher

Video Guide for React Native

Setup Application in Authgear

From the Project listing, create a new Project or select an existing Project. After that, we will need to create an application in the project.

Step 1: Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application and select Native App as the application type. Click "Save".

  4. You will see a list of guides that can help you for setting up, then click "Next".

Step 2: Configure the application

  1. Head back to Authgear Portal, fill in the URI that you have defined in the previous steps.

  2. Click "Save" in the top tool bar and keep the Client ID. You can also obtain it again from the Applications list later.

oauth:
  clients:
    - name: your_app_name
      client_id: a_random_generated_string
      redirect_uris:
        - "com.myapp://host/path"
      grant_types:
        - authorization_code
        - refresh_token
      response_types:
        - code
        - none

Create a React Native app

Follow the documentation of React Native to see how you can create a new React Native app.

npx react-native init myapp
cd myapp

Install the SDK

yarn add --exact @authgear/react-native
(cd ios && pod install)

Platform Integration

To finish the integration, setup the app to handle the redirectURI specified in the application. This part requires platform specific integration.

Android

Add the following activity entry to the AndroidManifest.xml of your app. The intent system would dispatch the redirect URI to OAuthRedirectActivity and the sdk would handle the rest.

<!-- Your application configuration. Omitted here for brevity -->
<application>
  <!-- Other activities or entries -->

  <!-- Add the following activity -->
  <!-- android:exported="true" is required -->
  <!-- See https://developer.android.com/about/versions/12/behavior-changes-12#exported -->
  <activity android:name="com.authgear.reactnative.OAuthRedirectActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Configure data to be the exact redirect URI your app uses. -->
                <!-- Here, we are using com.authgear.example://host/path as configured in authgear.yaml. -->
                <!-- NOTE: The redirectURI supplied in AuthenticateOptions *has* to match as well -->
                <data android:scheme="com.myapp.example"
                    android:host="host"
                    android:pathPrefix="/path"/>
            </intent-filter>
  </activity>
</application>

Targeting API level 30 or above (Android 11 or above)

If your Android app is targeting API level 30 or above (Android 11 or above), you need to add a queries section to AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- Other elements such <application> -->
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

iOS

Declare URL Handling in Info.plist

In Info.plist, add the matching redirect URI.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
      <!-- Other entries -->
      <key>CFBundleURLTypes</key>
      <array>
              <dict>
                      <key>CFBundleTypeRole</key>
                      <string>Editor</string>
                      <key>CFBundleURLSchemes</key>
                      <array>
                              <string>com.myapp.example</string>
                      </array>
              </dict>
      </array>
</dict>
</plist>

Insert the SDK Integration Code

In AppDelegate.m, add the following code snippet.

// Other imports...
#import <authgear-react-native/AGAuthgearReactNative.h>

// Other methods...

// For handling deeplink
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:
                (NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
    return [AGAuthgearReactNative application:app openURL:url options:options];
}

// For handling deeplink
// deprecated, for supporting older devices (iOS < 9.0)
- (BOOL)application:(UIApplication *)application
              openURL:(NSURL *)url
    sourceApplication:(NSString *)sourceApplication
          annotation:(id)annotation {
    return [AGAuthgearReactNative application:application
                                      openURL:url
                            sourceApplication:sourceApplication
                                  annotation:annotation];
}

// for handling universal link
- (BOOL)application:(UIApplication *)application
    continueUserActivity:(NSUserActivity *)userActivity
      restorationHandler:
          (void (^)(NSArray<id<UIUserActivityRestoring>> *_Nullable))
              restorationHandler {
    return [AGAuthgearReactNative application:application
                        continueUserActivity:userActivity
                          restorationHandler:restorationHandler];
}

Try authenticate

Add this code to your react native app. This snippet configures authgear to connect to an authgear server deployed at endpoint with the client you have just setup via clientID, opens a browser for authentication, and then upon success redirects to the app via the redirectURI specified.

import React, { useCallback } from "react";
import { View, Button } from "react-native";
import authgear from "@authgear/react-native";

function LoginScreen() {
  const onPress = useCallback(() => {
    // Normally you should only configure once when the app launches.
    authgear
      .configure({
        clientID: "client_id",
        endpoint: "http://<myapp>.authgear.cloud",
      })
      .then(() => {
        authgear
          .authenticate({
            redirectURI: "com.myapp.example://host/path",
          })
          .then(({ userInfo }) => {
            console.log(userInfo);
          });
      });
  }, []);

  return (
    <View>
      <Button onPress={onPress} title="Authenticate" />
    </View>
  );
}

Now, your user is logged in!

Get the Logged In State

When you start launching the application. You may want to know if the user has logged in. (e.g. Show users the login page if they haven't logged in). The sessionState reflects the user logged in state in the SDK local state. That means even the sessionState is AUTHENTICATED, the session may be invalid if it is revoked remotely. After initializing the Authgear SDK, call fetchUserInfo to update the sessionState as soon as it is proper to do so.

// After authgear.configure, it only reflect SDK local state.
// value can be NO_SESSION or AUTHENTICATED
let sessionState = authgear.sessionState;

if (sessionState === "AUTHENTICATED") {
    authgear
        .fetchUserInfo()
        .then((userInfo) => {
            // sessionState is now up to date
        })
        .catch((e) => {
            // sessionState is now up to date
            // it will change to NO_SESSION if the session is invalid
        });
}

The value of sessionState can be UNKNOWN, NO_SESSION or AUTHENTICATED. Initially the sessionState is UNKNOWN. After a call to authgear.configure, the session state would become AUTHENTICATED if a previous session was found, or NO_SESSION if such session was not found.

Fetching User Info

Using the Access Token in HTTP Requests

To include the access token to the HTTP requests to your application server, there are two ways to achieve this.

Option 1: Using fetch function provided by Authgear SDK

authgear
    .fetch("YOUR_SERVER_URL")
    .then(response => response.json())
    .then(data => console.log(data));

Option 2: Add the access token to your HTTP

You can access the access token through authgear.accessToken. Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of your application request.

authgear
    .refreshAccessTokenIfNeeded()
    .then(() => {
        // access token is ready to use
        // accessToken can be string or undefined
        // it will be empty if user is not logged in or session is invalid
        const accessToken = authgear.accessToken;

        // include Authorization header in your application request
        const headers = {
            Authorization: `Bearer ${accessToken}`
        };
    });

Logout

To log out the user from the current app session, you need to invoke the logout function.

authgear
  .logout()
  .then(() => {
    // logout successfully
  });

Next steps

To protect your application server from unauthorized access. You will need to integrate your backend with Authgear.

JavaScript SDK Reference

Native/Mobile App

If you are developing mobile or desktop applications, choose from one of these SDKs for your platform to get started.

React

Follow this quickstart tutorial to add authentication to your React application

Authgear helps you add user logins to your React apps. It provides prebuilt login page and user settings page that accelerate the development.

Table of Content

Setup Application in Authgear

After that, we will need to create an Application in the Project Portal.

Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application, e.g. "MyAwesomeApp".

  4. Select Single Page Application as the application type

  5. Click "Save" to create the application

Configure Authorize Redirect URI

The Redirect URI is a URL in you application where the user will be redirected to after login with Authgear. In this path, make a finish authentication call to complete the login process.

For this tutorial, add http://localhost:4000/auth-redirect to Authorize Redirect URIs.

Configure Post Logout Redirect URI

The Post Logout Redirect URI is the URL users will be redirected after they have logged out. The URL must be whitelisted.

For this tutorial, add http://localhost:4000/ to Post Logout Redirect URIs.

Save the configuration before next steps.

Step 1: Create a simple React project

Install basic project dependencies

Create the project folder and install the dependencies. We will use parcel as the build tool and the react-router-dom, react , and react-dom packages. Also, we will use TypeScript in this tutorial.

Add script for launching the app

In the package.json file, add these two lines to the script section

The start script run the app in development mode on port 4000. The build script build the app for production to the dist/ folder.

Create the index.html file

In src/, create a new file called index.html for parcel to bundle the app:

src/index.html:

Create the App.tsx file

Create a new file called App.tsx with simply showing Hello World in the screen:

Create the index.tsx file

Create a new file called index.tsx as the entry point of the application.

The file structure in your project is now:

Run npm start now to run the project and you will see "Hello World" on http://localhost:4000.

Step 2: Install Authgear SDK to the project

Run the following command within your React project directory to install the Authgear Web SDK

In src/index.tsx , import authgear and call the configure function to initialize an Authgear instance on application loads.

It is recommend to render the app after configure() resolves. So by the time the app is rendered, Authgear is ready to use.

Run npm start now and you should see a page with "Hello World" and no error message in the console if Authgear SDK is configured successfully

Step 3: Implement the Context Provider

Since we want to reference the logged in state in anywhere of the app, let's put the state in a context provider with UserProvider.tsx in the /src/context folder.

In UserProvider.tsx, it will have a isLoggedIn boolean and a setIsLoggedIn function. The is LoggedIn boolean state can be auto updated using the onSessionStateChange callback. This callback can be stored in delegate which is in the local SDK container.

Step 4: Implement the Auth Redirect

Next, we will add an "AuthRedirect" page for handling the authentication result after the user have been authenticated by Authgear.

Create the AuthRedirect.tsx component file in the src/ folder.

Call the Authgear finishAuthentication() function in the Auth Redirect component to send a token back to Authgear server in exchange for access token and refresh token. Don't worry about the technical jargons, finishAuthentication() will do all the hard work for you and and save the authentication data.

When the authentication is finished, the isLoggedIn state from the UserContextProvider will automatic set to true. Finally, navigate back to root (/) which is our Home page.

The final AuthRedirect.tsx will look like this

Without a cleanup function, anuseEffectHook will be fired twice and hence finishAuthentication() will send the token back to Authgear Endpoint for two times, which the second one will result in "Invalid Token" error since the token can only be used once.

Step 5: Add Routes and Context Provider to the App

Next, we will add a "Home" page . Create a Home.tsx component file the src/ folder.

Then import Home and AuthRedirect as routes. And Import UserContextProvider and wrap the routes with it.

Your final App.tsx should look like this:

The file structure should now look like

Step 6: Add a Login button

First we will import the Authgear dependency and the React Hook that we will use to Home.tsx. Then add the login button which will call startAuthentication(ConfigureOptions) through startLogin callback on click. This will redirect the user to the login page.

You can now run npm start and you will be redirected to the Authgear Login page when you click the Login button.

Step 7: Show the user information

The Authgear SDK helps you get the information of the logged in users easily.

In the last step, the user is successfully logged in so let's try to print the user ID (sub) of the user in the Home page.

In Home.tsx, we will add a simple Loading splash and a greeting message printing the Sub ID. We will add two conditional elements such that they are only shown when user is logged in. We can also change the login button to show only if the user is not logged in.

Make use of isLoggedIn from the UserContext to control the components on the page. Fetch the user info by fetchInfo() and access its sub property.

Run the app again, the User ID (sub) of the user should be printed on the Home page.

Step 8: Add a Logout button

Finally, let's add an Logout button when user is logged in.

In Home.tsx, we will add a conditional elements in the elements:

And add the logout callback:

Run the app again, we can now logout by clicking the logout button.

Step 9: Open User Settings

Authgear provide a built-in UI for the users to set their attributes and change security settings.

Use the openURL function to open the setting page at <your_app_endpoint>/settings

In Home.tsx Add a conditional link to the elements.

And add the userSetting callback:

This the the resulting Home.tsx:

Next steps, Calling an API

To access restricted resources on your backend application server, the HTTP requests should include the access token in their Authorization headers. The Web SDK provides a fetch function which automatically handle this, or you can get the token with authgear.accessToken.

Option 1: Using fetch function provided by Authgear SDK

Option 2: Add the access token to the HTTP request header

You can get the access token through authgear.accessToken. Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of the application request.

Android Kotlin coroutine support

The Authgear Android SDK comes with kotlin support out of the box. In fact, the SDK is written in kotlin!

If you are using kotlin, you can benefit from the suspend function APIs authgear provides. For example, the above authorize example can be written as follows:

iOS SDK

Integrate your iOS application with Authgear iOS SDK

This guide provides instructions on integrating Authgear with an iOS app. Supported platforms include:

  • iOS 11.0 or higher

Setup Application in Authgear

From the Project listing, create a new Project or select an existing Project. After that, we will need to create an application in the project.

Install the SDK

CocoaPods

Swift Package Manager

Register URL Scheme for Redirect URI

In your application's Info.plist , register your custom URL scheme, (e.g. com.myapp).

Configuration Authgear SDK

SDK must be properly configured before use.

Trigger authenticate

When the user clicks login/signup on your app, you can use the following code to start authorization.

Your user is now logged in!

Get the Logged In State

When you start launching the application. You may want to know if the user has logged in. (e.g. Show users the login page if they haven't logged in). The sessionState reflects the user logged in state in the SDK local state. That means even the sessionState is .authenticated, the session may be invalid if it is revoked remotely. After initializing the Authgear SDK, call fetchUserInfo to update the sessionState as soon as it is proper to do so.

The value of sessionState can be .unknown, .noSession or .authenticated. Initially, the sessionState is .unknown. After a call to authgear.configure, the session state would become .authenticated if a previous session was found, or .noSession if such session was not found.

Fetching User Info

Using the Access Token in HTTP Requests

Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of your application request.

Logout

To log out the user from the current app session, you need to invoke thelogoutfunction.

Next steps

To protect your application server from unauthorized access. You will need to integrate your backend with Authgear.

iOS SDK Reference

Footnote

To start using Authgear in your application, create a free Authgear account on .

Now that you have created a project in Authgear, you're ready to integrate Authgear into your applications for your customers/users to sign up and log in. See our documentation for adding Authgear to your application or website for your favourite framework and programming language.

You can learn more about the User Settings page .

Authgear has official SDKs for integrating Authgear with React, React Native, ionic, Native Android, iOS, and Flutter applications. See the section of Authgear documentation for detailed instructions for each SDK and using other frameworks without the official SDK.

login and sign-up page to match your branding needs using the Design tool

guides on how to .

how to .

Follow this 15 minutes tutorial to create a simple app using Angular with Authgear SDK.

Check out and clone .

Signup for an account in and create a Project.

Configure Authorized Redirect URIs and Post Logout Redirect URIs.

For Windows clients, please find your reference in for more information on installing the Angular CLI.

User will be redirected to the Authgear login page by clicking the login button
Show the User ID, a link to User Settings and a logout button after login

Authgear SDK provides the fetch function for you to call your application server. This fetch function will include the Authorization header in your application request, and handle refresh access token automatically. The authgear.fetch implements .

Follow this 15 minutes tutorial to create a simple app using Vue with Authgear SDK.

Check out and clone .

Signup for an account in and create a Project.

Configure Authorized Redirect URIs and Post Logout Redirect URIs.
User will be redirected to the Authgear login page by clicking the login button
Show the User ID, a link to User Settings and a logout button after login

Authgear SDK provides the fetch function for you to call your application server. This fetch function will include the Authorization header in your application request, and handle refresh access token automatically. The authgear.fetch implements .

React Native have opt-in support for the since 0.68. Given that the New Architecture is still considered as unstable, we do not support it at the moment.

Signup for an Authgear Portal account in . Or you can use your self-deployed Authgear.

Create an application

In your IDE, define a custom URI scheme that the users will be redirected back to your app after they have authenticated with Authgear, e.g. com.myapp.example://host/path. For further instruction on setting up custom URI scheme in React Native, see

Edit an application

If you wish to , turn on "Issue JWT as access token". If you wish to , leave this unchecked. See comparisons in . For more explanation on JWT, see

In some cases, you may need to obtain current user info through the SDK. (e.g. Display email address in the UI). Use the fetchUserInfo function to obtain the user info, see .

Authgear SDK provides the fetch function for you to call your application server. The fetch function will include the Authorization header in your application request, and handle refresh access token automatically. authgear.fetch implement .

For detailed documentation on the JavaScript React Native SDK, visit

Follow this 15 minutes tutorial to create a simple app using React with Authgear SDK.

Check out and clone .

Signup for an account in and create a Project.

Here are some recommended steps to scaffold a React project. You can skip this part if you are adding Authgear to an existing project. See in the next section.

The Authgear container instance takes endpoint and clientID as parameters. They can be obtained from the application page created in .

Since in React 18, useEffect will be fired twice in development mode, we need to implement a to stop it from firing twice. We will use an useRef Hook to stop the user token from being sent twice to the Authgear Endpoint.

Authgear SDK provides the fetch function for you to call your application server. This fetch function will include the Authorization header in your application request, and handle refresh access token automatically. The authgear.fetch implements .

Signup for an Authgear Portal account in . Or you can use your self-deployed Authgear.

Step 1: Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application and select Native App as the application type. Click "Save".

  4. You will see a list of guides that can help you for setting up, then click "Next".

Step 2: Configure the application

  1. In your IDE (e.g. XCode), define a custom URI scheme that the users will be redirected back to your app after they have authenticated with Authgear, e.g. com.myapp.example://host/path.[^1]

  2. Head back to Authgear Portal, fill in the Redirect URI that you have defined in the previous steps.

  3. Click "Save" in the top tool bar and keep the Client ID. You can also obtain it again from the Applications list later.

In some cases, you may need to obtain current user info through the SDK. (e.g. Display email address in the UI). Use the fetchUserInfo function to obtain the user info, see .

For detailed documentation on the iOS SDK, visit .

[^1]: For further instruction on setting up custom URI scheme in iOS, see [^2]: For more explanation on JWT, see

If you wish to , turn on "Issue JWT as access token".[^2] If you wish to , leave this unchecked. See comparisons in .

🕐
🕐
authgear.com
here
here
Start Building
Admin API
customize the look of AuthUI
integrate Authgear to your app
enable 2FA for your project
the Sample Project on GitHub
https://portal.authgear.com/
https://angular.io/guide/setup-local
fetch
the Sample Project on GitHub
https://portal.authgear.com/
fetch
New Architecture
https://portal.authgear.com/
https://reactnative.dev/docs/linking
validate JSON Web Token (JWT) in your own application server
forward authentication requests to Authgear Resolver Endpoint
Backend Integration
https://en.wikipedia.org/wiki/JSON_Web_Token
fetch
Backend Integration
@authgear/react-native Reference
Android SDK
Flutter SDK
iOS SDK
React Native SDK
Ionic SDK
Xamarin SDK
Setup Application in Authgear
Create a simple Angular project
Install Authgear SDK to the project
Implement User Service
Implement the Auth Redirect page
Add a Login button
Show the user information
Add a Logout button
Open User Settings
Calling an API
Setup Application in Authgear
Create a simple Vue project
Create routes for the project
Install Authgear SDK to the project
Implement Context Provider
Implement the Auth Redirect page
Add a Login button
Show the user information
Add a Logout button
Open User Settings
Calling an API
# Create a new folder for your project
mkdir my-app
# Move into the project directory
cd my-app
# Create source folder
mkdir src
# Create a brand new package.json file
npm init -y
# Install parcel
npm install --save-dev --save-exact parcel
# Install react, react-dom and react router
npm install --save-exact react react-dom react-router-dom
# Install TypeScript and related types
npm install --save-dev --save-exact typescript @types/react @types/react-dom @types/react-router-dom
"start": "parcel serve --port 4000 --no-cache ./src/index.html",
"build": "parcel build --no-cache ./src/index.html"
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Authgear React Tutorial Demo App</title>
  </head>
  <body>
    <div id="react-app-root"></div>
    <script type="module" src="./index.tsx"></script>
  </body>
</html>
// src/App.tsx
import React from "react";

const App: React.FC = () => {
  return <div>Hello World</div>;
};

export default App;
// src/index.tsx
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

async function init() {
  try {
   // initialization code
  } finally {
    createRoot(document.getElementById("react-app-root")!).render(<App />);
  }
}

init().catch((e) => {
  // Error handling
  console.error(e)
});
 
my-app
├── node_modules
│   └── (...)
├── package-lock.json
├── package.json
└── src
    ├── App.tsx
    ├── index.html
    └── index.tsx
npm install --save --save-exact @authgear/web
// src/index.tsx
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import authgear from "@authgear/web";

async function init() {
  try {
    // configure Authgear container instance
    await authgear.configure({
      endpoint: "<your_app_endpoint>",
      clientID: "<your_client_id>",
      sessionType: "refresh_token",
    });
  } finally {
    createRoot(document.getElementById("react-app-root")!).render(<App />);
  }
}

init().catch((e) => {
  // Error handling
  console.error(e)
});
// src/context/UserProvider.tsx
import React, { createContext, useEffect, useState, useMemo } from "react";
import authgear from "@authgear/web";

interface UserContextValue {
  isLoggedIn: boolean;
}

export const UserContext = createContext<UserContextValue>({
  isLoggedIn: false,
});

interface UserContextProviderProps {
  children: React.ReactNode;
}

const UserContextProvider: React.FC<UserContextProviderProps> = ({
  children,
}) => {
  // By default the user is not logged in
  const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);

  useEffect(() => {
    // When the sessionState changed, logged in state will also be changed
    authgear.delegate = {
      onSessionStateChange: (container) => {
        // sessionState is now up to date
        // Value of sessionState can be "NO_SESSION" or "AUTHENTICATED"
        const sessionState = container.sessionState;
        if (sessionState === "AUTHENTICATED") {
          setIsLoggedIn(true);
        } else {
          setIsLoggedIn(false);
        }
      },
    };
  }, [setIsLoggedIn]);

  const contextValue = useMemo<UserContextValue>(() => {
    return {
      isLoggedIn,
    };
  }, [isLoggedIn]);

  return (
    <UserContext.Provider value={contextValue}>{children}</UserContext.Provider>
  );
};

export default UserContextProvider;
// src/AuthRedirect.tsx
import React, { useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import authgear from "@authgear/web";

const AuthRedirect: React.FC = () => {
  const usedToken = useRef(false);

  const navigate = useNavigate();

  useEffect(() => {
    async function updateToken() {
      try {
        await authgear.finishAuthentication();
      } finally {
        navigate("/");
        usedToken.current = true;
      }
    }

    if (!usedToken.current) {
      updateToken().catch((e) => console.error(e));
    }
  }, [navigate]);

  return <></>;
};

export default AuthRedirect;
// src/App.tsx
import React from "react";
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import AuthRedirect from './AuthRedirect';
import UserContextProvider from './context/UserProvider';

const App: React.FC = () => {
  return (
    <UserContextProvider>
      <Router>
        <Routes>
          <Route path="/auth-redirect" element={<AuthRedirect />} />
          <Route path="/" element={<Home />} />
        </Routes>
      </Router>
    </UserContextProvider>
  );
}

export default App;
src
├── App.tsx
├── AuthRedirect.tsx
├── Home.tsx
├── context
│   └── UserProvider.tsx
├── index.html
└── index.tsx
// src/Home.tsx
import React, { useEffect, useState, useCallback, useContext } from 'react';
import authgear from '@authgear/web';

const Home: React.FC = () => {
  const startLogin = useCallback(() => {
    authgear
      .startAuthentication({
        redirectURI: 'http://localhost:4000/auth-redirect',
        prompt: 'login'
      })
      .then(
        () => {
          // started authentication, user should be redirected to Authgear
        },
        err => {
          // failed to start authentication
        }
      );
  }, []);
  return (
    <div>
      <h1>Home Page</h1>
      <div>
        <button onClick={startLogin}>Login</button>
      </div>
    </div>
  );
}

export default Home;
// src/Home.tsx  
import React, { useEffect, useState, useCallback, useContext } from "react";
import authgear from "@authgear/web";
import { UserContext } from "./context/UserProvider";

const Home: React.FC = () => {
  const [greetingMessage, setGreetingMessage] = useState<string>("");
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const { isLoggedIn } = useContext(UserContext);

  useEffect(() => {
    async function updateGreetingMessage() {
      setIsLoading(true);
      try {
        if (isLoggedIn) {
          const userInfo = await authgear.fetchUserInfo();
          setGreetingMessage("The current User sub: " + userInfo.sub);
        }
      } finally {
        setIsLoading(false);
      }
    }

    updateGreetingMessage().catch((e) => {
      console.error(e);
    });
  }, [isLoggedIn]);

  const startLogin = useCallback(() => {
    authgear
      .startAuthentication({
        redirectURI: "http://localhost:4000/auth-redirect",
        prompt: "login",
      })
      .then(
        () => {
          // started authentication, user should be redirected to Authgear
        },
        (err) => {
          // failed to start authentication
        }
      );
  }, []);

  return (
    <div>
      <h1>Home Page</h1>
      {isLoading && "Loading"}
      {greetingMessage ? <span>{greetingMessage}</span> : null}
      {!isLoggedIn && (
        <div>
          <button type="button" onClick={startLogin}>
            Login
          </button>
        </div>
      )}
    </div>
  );
};

export default Home;
{isLoggedIn && (
  <div>
    <button onClick={logout}>Logout</button>
  </div>
)}
const logout = useCallback(() => {
  authgear
    .logout({
      redirectURI: "http://localhost:4000/",
    })
    .then(
      () => {
        setGreetingMessage('');
      },
      (err) => {
        console.error(err);
      }
  );
}, []);
{isLoggedIn && (
  <a target="_blank" rel="noreferrer" onClick={userSetting} href="#">
    User Setting
  </a>
)}
import authgear, { Page } from "@authgear/web";
const userSetting = useCallback((e: React.MouseEvent<HTMLAnchorElement>) => {
    e.preventDefault();
    e.stopPropagation();
    authgear.open(Page.Settings);
}, []);
// src/Home.tsx
import React, { useEffect, useState, useCallback, useContext } from "react";
import { UserContext } from "./context/UserProvider";
import authgear, { Page } from "@authgear/web";

const Home: React.FC = () => {
  const [greetingMessage, setGreetingMessage] = useState<string>("");
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const { isLoggedIn } = useContext(UserContext);

  useEffect(() => {
    async function updateGreetingMessage() {
      setIsLoading(true);
      try {
        if (isLoggedIn) {
          const userInfo = await authgear.fetchUserInfo();
          setGreetingMessage("The current User sub: " + userInfo.sub);
        }
      } finally {
        setIsLoading(false);
      }
    }

    updateGreetingMessage().catch((e) => {
      console.error(e);
    });
  }, [isLoggedIn]);

  const startLogin = useCallback(() => {
    authgear
      .startAuthentication({
        redirectURI: "http://localhost:4000/auth-redirect",
        prompt: "login",
      })
      .then(
        () => {
          // started authorization, user should be redirected to Authgear
        },
        (err) => {
          // failed to start authorization
          console.error(err);
        }
      );
  }, []);

  const logout = useCallback(() => {
    authgear
      .logout({
        redirectURI: "http://localhost:4000/",
      })
      .then(
        () => {
          setGreetingMessage("");
        },
        (err) => {
          console.error(err);
        }
      );
  }, []);

  const userSetting = useCallback((e: React.MouseEvent<HTMLAnchorElement>) => {
    e.preventDefault();
    e.stopPropagation();
    authgear.open(Page.Settings);
  }, []);

  return (
    <div>
      {/* eslint-disable-next-line react/forbid-elements */}
      <h1>Home Page</h1>
      {isLoading && "Loading"}
      {greetingMessage ? <span>{greetingMessage}</span> : null}
      {!isLoggedIn && (
        <div>
          <button type="button" onClick={startLogin}>
            Login
          </button>
        </div>
      )}
      {isLoggedIn && (
        <div>
          <button type="button" onClick={logout}>
            Logout
          </button>
          <br />
          <a target="_blank" rel="noreferrer" onClick={userSetting} href="#">
            User Setting
          </a>
        </div>
      )}
    </div>
  );
};

export default Home;
authgear
    .fetch("YOUR_SERVER_URL")
    .then(response => response.json())
    .then(data => console.log(data));
authgear
    .refreshAccessTokenIfNeeded()
    .then(() => {
        // access token is ready to use
        // accessToken can be string or undefined
        // it will be empty if user is not logged in or session is invalid
        const accessToken = authgear.accessToken;

        // include Authorization header in your application request
        const headers = {
            Authorization: `Bearer ${accessToken}`
        };
    });
import kotlinx.coroutines.*

class MyAwesomeViewModel(application: MyAwesomeApplication) : AndroidViewModel(application) {
    // Other methods

    // This is called when login button is clicked.
    fun login() {
        viewModelScope {
            withContext(Dispatchers.IO) {
                try {
                    val app = getApplication<MyAwesomeApplication>()
                    val state = app.authgear.authenticate(AuthenticateOptions(redirectUri = "com.myapp://host/path"))
                    // User is logged in!
                } catch (e: Throwable) {
                    // Something went wrong.
                }
            }
        }
    }
}
oauth:
  clients:
    - name: your_app_name
      client_id: a_random_generated_string
      redirect_uris:
        - "com.myapp://host/path"
      grant_types:
        - authorization_code
        - refresh_token
      response_types:
        - code
        - none
pod 'Authgear', :git => 'https://github.com/authgear/authgear-sdk-ios.git'
dependencies: [
    .package(url: "https://github.com/authgear/authgear-sdk-ios.git")
]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <!-- Other entries -->
        <key>CFBundleURLTypes</key>
        <array>
            <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLSchemes</key>
                <array>
                    <string>{YOUR_CUSTOM_URL_SCHEME}</string>
                </array>
            </dict>
        </array>
    </dict>
</plist>
// your_app_endpoint should looks like this https://<yourapp>.authgear.cloud
let authgear = Authgear(clientId: "{your_clien_id}", endpoint: "{your_app_endpoint}")
authgear.configure() { result in
    switch result {
    case .success():
        // configured successfully
    case let .failure(error):
        // failed to configured
    }
}
// your_redirect_uri is redirect uri registered on the applications page
// e.g. com.myapp://host/path
authgear.authenticate(redirectURI: "{your_redirect_uri}", handler: { result in
    switch result {
    case let .success(userInfo):
        // login successfully
    case let .failure(error):
        if let authgearError = error as? AuthgearError, case .cancel = authgearError {
            // user cancel
        } else {
            // Something went wrong
        }
    }
})
// After authgear.configure, it only reflect SDK local state.
// value can be .noSession or .authenticated
var sessionState = authgear.sessionState

authgear.fetchUserInfo { userInfoResult in
    // sessionState is now up to date
    // it will change to .noSession if the session is invalid
    sessionState = authgear.sessionState

    switch userInfoResult {
    case let .success(userInfo):
        // read the userInfo if needed
    case let .failure(error):
        // failed to fetch user info
        // the refresh token maybe expired or revoked
}
authgear.refreshAccessTokenIfNeeded() { result in
    switch result {
    case .success():
        // access token is ready to use
        // accessToken can be empty
        // it will be empty if user is not logged in or session is invalid

        // include Authorization header in your application request
        if let accessToken = authgear.accessToken {
            // example only, you can use your own networking library
            var urlRequest = URLRequest(url: "YOUR_SERVER_URL")
            urlRequest.setValue(
                "Bearer \(accessToken)", forHTTPHeaderField: "authorization")
            // ... continue making your request
        } else {
            // The user is not logged in, or the token is expired.
        }
    case let .failure(error):
        // Something went wrong
    }
}
authgear.logout { result in
    switch result {
        case .success():
            // logout successfully
        case let .failure(error):
            // failed to login
    }
}
#install-authgear-sdk-to-the-project
Setup Application in Authgear
Configure Authorized Redirect URIs and Post Logout Redirect URIs.
User will be redirected to the Authgear login page by clicking the login button
Show the User ID, a link to User Settings and a logout button after login
Create an application
Edit an application
🕐
the Sample Project on GitHub
https://portal.authgear.com/
cleanup function
fetch
https://portal.authgear.com/
validate JSON Web Token (JWT) in your own application server
forward authentication requests to Authgear Resolver Endpoint
Backend Integration
Backend Integration
iOS SDK Reference
https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app
https://en.wikipedia.org/wiki/JSON_Web_Token
Setup Application in Authgear
Create a simple React project
Install Authgear SDK to the project
Implement Context Provider
Implement the Auth Redirect page
Add a Login button
Show the user information
Add a Logout button
Open User Settings
Calling an API

Next.js

Authentication for Next.js app with Authgear

Learning objectives

You will learn the following throughout the article:

  • How to add user login, sign-up, and logout to Next.js Applications.

  • How to create a middleware to protect Next.js application pages.

Implementing authentication in a Next.js web app

Prerequisites

Before you begin, you'll need the following:

Part 1: Configure Authgear

Step 1: Configure an application

Step 2: Configure Redirect URI

Step 3: Choose a Login method

After you created the Authgear app, you choose how users need to authenticate on the login page. From the Authentication tab, navigate to Login Methods, you can choose a login method from various options including, by email, mobile, or social, just using a username or the custom method you specify. For this demo, we choose the Email+Passwordless approach where our users are asked to register an account and log in by using their emails. They will receive a One-time password (OTP) to their emails and verify the code to use the app.

Part 2: Create the Next.js application

Clone the demo repository

git clone https://github.com/authgear/authgear-example-nextjs.git

Since you've cloned a working repo, you don't need to follow the next section. If you'd like to understand more about what was done in the demo application, feel free to read them.

Step 1: Create your own Next.js application

If you want to create your own application instead of using our demo project, you can create a new Next.js application by running the command below.

npx create-next-app authgear-example-nextjs

The create-next-app wizard will ask you a few questions on how to set up your application. Answer them accordingly.

Step 2: Installing NextAuth.js

npm install next-auth

Now, you need to create a file named exactly like [...nextauth].js in src/pages/api/auth. First, make the directory and then create a file named [...nextauth].js in that directory.

In the following code, we made a few config:

  1. We have made id and name in the Next Auth session (under callbacks). You can also add other attributes such as email, phone_number, and preferred_username to the session as well.

import NextAuth from "next-auth"

export const authOptions = {
    providers: [
        {
            id: "authgear",
            name: "Authgear",
            type: "oauth",
            issuer: process.env.AUTHGEAR_ISSUER,
            clientId: process.env.AUTHGEAR_CLIENT_ID,
            clientSecret: process.env.AUTHGEAR_CLIENT_SECRET,
            wellKnown: `${process.env.AUTHGEAR_ISSUER}/.well-known/openid-configuration`,
            authorization: { params: { scope: "openid offline_access https://authgear.com/scopes/full-userinfo" } },
            client: {
                token_endpoint_auth_method: "client_secret_post",
            },
            profile(profile) {
              return {
                id: profile.sub,
              }
            },
          }
    ],
    callbacks: {
        async jwt({ token, account, profile }) {
            if (account) {
                token.accessToken = account.access_token

                token.id = profile.sub
                token.name = profile.name
            }
            return token
        },

        async session({ session, token, user }) {
            session.accessToken = token.accessToken

            session.user.id = token.id
            session.user.name = token.name

            return session
        }
    },
}

export default NextAuth(authOptions)

Step 3: Exposing session state

To allow components to check whether the current user is logged in, change src/pages/_app.js to have your application rendered inside a <SessionProvider> context, as shown below.

import '@/styles/globals.css'
import { SessionProvider } from "next-auth/react"

export default function App({
    Component,
    pageProps: {session, ...pageProps},
}) {
    return (
        <SessionProvider session={session}>
            <Component {...pageProps} />
        </SessionProvider>
    );
}
import { useSession, signIn, signOut } from "next-auth/react"

export default function Component() {
    const { data: session } = useSession()
    if (session) {
        return (
            <>
                Status: Logged in as {session.user.id} <br />
                <button onClick={() => signOut()}>Log out</button>
            </>
        )
    }
    return (
        <>
            Status: Not logged in <br />
            <button onClick={() => signIn()}>Log in</button>
        </>
    )
}

Then, you change your home component located at src/pages/index.js to include the <LoginButton /> component inside <main>.

import { useSession, signIn, signOut } from "next-auth/react"

export default function Component() {
    const { data: session } = useSession()
    if (session) {
        return (
            <>
                Status: Logged in as {session.user.id} <br />
                <button onClick={() => signOut()}>Log out</button>
            </>
        )
    }
    return (
        <>
            Status: Not logged in <br />
            <button onClick={() => signIn()}>Log in</button>
        </>
    )
}

Step 4: Set environment variables

In the root directory of your project, add the file .env.local with the following environment variables:

AUTHGEAR_ISSUER={your-authgear-app-endpoint}
AUTHGEAR_CLIENT_ID={your-client-id}
AUTHGEAR_CLIENT_SECRET={your-client-secret}

replace with Authgear app settings values from Part1 such as Issuer, ClientId, ClientSecret.

Step 5: Testing

Start the HTTP server by running the following command.

npm run dev

Click the "Log in" button to be taken to a page with a "Sign in with Authgear" button.

After clicking it, you should be redirected to your Authgear login screen.

After you have authenticated with a one-time password sent to your email, you'll arrive back at your Next.js application home screen, with your email address displayed and a "Log out" button.

Next steps

This tutorial showed how to quickly implement an end-to-end OpenID Connect flow in Next.js with Authgear. Only simple code is needed, after which protected views are secured with built-in UI login pages.

Flutter SDK

How to integrate with a Flutter app

This guide provides instructions on integrating Authgear with a Flutter app. Supported platforms include:

  • Flutter 2.5.0 or higher

Setup Application in Authgear

From the Project listing, create a new Project or select an existing Project. After that, we will need to create an application in the project.

Create a Flutter app

Follow the documentation of Flutter to see how you can create a new Flutter app.

flutter create myapp
cd myapp

Install the SDK

flutter pub add flutter_authgear

Platform Integration

To finish the integration, setup the app to handle the redirectURI specified in the application. This part requires platform specific integration.

This declares the URL schemes supported by your app, so the device can redirect the user to the app after authentication using the redirect URI.

Android

Add the following <activity> entry to the AndroidManifest.xml of your app. The intent system would dispatch the redirect URI to OAuthRedirectActivity and the SDK would handle the rest.

<!-- Your application configuration. Omitted here for brevity -->
<application>
  <!-- Other activities or entries -->

  <!-- Add the following activity -->
  <!-- android:exported="true" is required -->
  <!-- See https://developer.android.com/about/versions/12/behavior-changes-12#exported -->
  <activity android:name="com.authgear.flutter.OAuthRedirectActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Configure data to be the exact redirect URI your app uses. -->
                <!-- Here, we are using com.authgear.example://host/path as configured in authgear.yaml. -->
                <!-- NOTE: The redirectURI supplied in AuthenticateOptions *has* to match as well -->
                <data android:scheme="com.myapp.example"
                    android:host="host"
                    android:pathPrefix="/path"/>
            </intent-filter>
  </activity>
</application>

Targeting API level 30 or above (Android 11 or above)

If your Android app is targeting API level 30 or above (Android 11 or above), you need to add a queries section to AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- Other elements such <application> -->
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

iOS

Declare URL Handling in Info.plist

In Info.plist, add the matching redirect URI by adding the key CFBundleURLTypes and the values inside <dict> as shown as the following example.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
      <!-- Other entries -->
      <key>CFBundleURLTypes</key>
      <array>
              <dict>
                      <key>CFBundleTypeRole</key>
                      <string>Editor</string>
                      <key>CFBundleURLSchemes</key>
                      <array>
                              <string>com.myapp.example</string>
                              <!-- Put the redirect URI your app uses here. -->
                      </array>
              </dict>
      </array>
</dict>
</plist>

Try authenticate

Add this code to your app. This snippet configures authgear to connect to an authgear server deployed at endpoint with the client you have just setup via clientID, opens a browser for authentication, and then upon success redirects to the app via the redirectURI specified.

import 'package:flutter/material.dart';
import 'package:flutter_authgear/flutter_authgear.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}


class _MyAppState extends State<MyApp> {
  late Authgear _authgear;

  @override
  void initState() {
    super.initState();
    _init();
  }

  Future<void> _init() async {
    _authgear = Authgear(endpoint: "ENDPOINT", clientID: "CLIENT_ID");
    await _authgear.configure();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "MyApp",
      home: Scaffold(
        appBar: AppBar(title: const Text("MyApp")),
        body: TextButton(
          child: Text("Authenticate"),
          onPressed: _onPressedAuthenticate,
        ),
      ),
    );
  }

  Future<void> _onPressedAuthenticate() async {
    try {
      await _authgear.authenticate(redirectURI: "REDIRECT_URI");
    } on CancelException {
    }
  }
}

Now, your user is logged in!

Get the Logged In State

When you start launching the application. You may want to know if the user has logged in. (e.g. Show users the login page if they haven't logged in). The sessionState reflects the user logged in state in the SDK local state. That means even the sessionState is SessionState.authenticated, the session may be invalid if it is revoked remotely. After initializing the Authgear SDK, call fetchUserInfo to update the sessionState as soon as it is proper to do so.

// After authgear.configure, it only reflect SDK local state.
// value can be SessionState.noSession or SessionState.authenticated
SessionState state = authgear.sessionState;

UserInfo? userInfo;
try {
  userInfo = await authgear.getUserInfo();
  // read the userInfo if needed
} catch (e) {
  // failed to fetch user info
  // the refresh token maybe expired or revoked
}
// sessionState is now up to date
// it will change to SessionState.noSession if the session is invalid
state = authgear.sessionState;

The value of sessionState can be SessionState.unknown, SessionState.noSession or SessionState.authenticated. Initially, the sessionState is SessionState.unknown. After a call to authgear.configure, the session state would become SessionState.authenticated if a previous session was found, or SessionState.noSession if such session was not found.

Fetching User Info

Using the Access Token in HTTP Requests

To include the access token to the HTTP requests to your application server, use wrapHttpClient.

The wrapped client will include the Authorization header in every HTTP request, and refresh access token automatically.

final originalClient = ...
final client = authgear.wrapHttpClient(originalClient);

Logout

To log out the user from the current app session, you need to invoke thelogoutfunction.

await authgear.logout();

Next steps

To protect your application server from unauthorized access. You will need to integrate your backend with Authgear.

Flutter SDK Reference

Footnote

Android SDK

How to use authgear android SDK

This guide provides instructions on integrating Authgear with an Android app. Supported platforms include:

  • Android 5.0 (API 21) or higher

Setup Application in Authgear

From the Project listing, create a new Project or select an existing Project. After that, we will need to create an application in the project.

Get the SDK

  1. Add jitpack repository to gradle

    allprojects {
        repositories {
            // Other repository
            maven { url 'https://jitpack.io' }
        }
    }
  2. Add authgear in dependencies. Use $branch-SNAPSHOT (e.g. main-SNAPSHOT) for the latest version in a branch or a release tag/git commit hash of the desired version.

    dependencies {
        // Other implementations
        implementation 'com.github.authgear:authgear-sdk-android:SNAPSHOT'
    }

Setup Redirect URI for Your Android App

Add the following activity entry to the AndroidManifest.xml of your app. The intent system would dispatch the redirect URI to OauthRedirectActivity and the SDK would handle the rest.

<!-- Your application configuration. Omitted here for brevity -->
<application>
  <!-- Other activities or entries -->

  <!-- Add the following activity -->
  <!-- android:exported="true" is required -->
  <!-- See https://developer.android.com/about/versions/12/behavior-changes-12#exported -->
  <activity android:name="com.oursky.authgear.OauthRedirectActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- Configure data to be the exact redirect URI your app uses. -->
                <!-- Here, we are using com.myapp://host/path as configured in authgear.yaml. -->
                <!-- NOTE: The redirectURI supplied in AuthenticateOptions *has* to match as well -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/path"/>
            </intent-filter>
  </activity>
</application>

Targeting API level 30 or above (Android 11 or above)

If your Android app is targeting API level 30 or above (Android 11 or above), you need to add a queries section to AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- Other elements such <application> -->
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

Initialize Authgear

public class MyAwesomeApplication extends Application {
    // The client ID of the oauth client.
    private static final String CLIENT_ID = "a_random_generated_string"
    // Deployed authgear's endpoint
    private static final String AUTHGEAR_ENDPOINT = "http://<myapp>.authgear.cloud/"
    private Authgear mAuthgear;
    public void onCreate() {
        super.onCreate();
        mAuthgear = new Authgear(this, CLIENT_ID, AUTHGEAR_ENDPOINT);
        mAuthgear.configure(new OnConfigureListener() {
            @Override
            public void onConfigured() {
                // Authgear can be used.
            }

            @Override
            public void onConfigurationFailed(@NonNull Throwable throwable) {
                Log.d(TAG, throwable.toString());
                // Something went wrong, check the client ID or endpoint.
            }
        });
    }

    public Authgear getAuthgear() {
        return mAuthgear;
    }
}

Authenticate a user

class MyAwesomeViewModel extends AndroidViewModel {
    // Other methods

    // This is called when login button is clicked.
    public void login() {
        MyAwesomeApplication app = getApplication();
        AuthenticateOptions options = new AuthenticateOptions("com.myapp://host/path");
        app.getAuthgear().authenticate(options, new OnAuthenticateListener() {
            @Override
            public void onAuthenticated(@Nullable UserInfo userInfo) {
                // The user is logged in!
            }

            @Override
            public void onAuthenticationFailed(@NonNull Throwable throwable) {
                if (throwable instanceof CancelException) {
                    // User cancel
                } else {
                    // Something went wrong.
                }
            }
        });
    }
}

The above call of authorize passes in the exact redirect URI as configured in the applications and manifest, the callback then indicates authorization success or failure. By default, the callback is called on the main thread.

Now, your user is logged in!

Get the Logged In State

When you start launching the application. You may want to know if the user has logged in. (e.g. Show users the login page if they haven't logged in). The SessionState reflects the user logged in state in the SDK local state. That means even the SessionState is AUTHENTICATED, the session may be invalid if it is revoked remotely. After initializing the Authgear SDK, call fetchUserInfo to update the SessionState as soon as it is proper to do so.

// After authgear.configure, it only reflect SDK local state.
// value can be NO_SESSION or AUTHENTICATED
SessionState state = mAuthgear.getSessionState();

mAuthgear.fetchUserInfo(new OnFetchUserInfoListener() {
    @Override
    public void onFetchedUserInfo(@NonNull UserInfo userInfo) {
        // sessionState is now up to date
        // read the userInfo if needed
    }

    @Override
    public void onFetchingUserInfoFailed(@NonNull Throwable throwable) {
        // sessionState is now up to date
        // it will change to NO_SESSION if the session is invalid
    }
});

The value of SessionState can be UNKNOWN, NO_SESSION or AUTHENTICATED. Initially, the sessionState is UNKNOWN. After a call to authgear.configure, the session state would become AUTHENTICATED if a previous session was found, or NO_SESSION if such session was not found.

Fetching User Info

Using the Access Token in HTTP Requests

// Suppose we are preparing an http request in a background thread.

// Setting up the request, e.g. preparing a URLConnection

try {
    authgear.refreshAccessTokenIfNeededSync();
} catch (OAuthException e) {
    // Something went wrong
}
String accessToken = authgear.getAccessToken();
if (accessToken == null) {
    // The user is not logged in, or the token is expired.
    // It is up to the caller to decide how to handle this situation.
    // Typically, the request could be aborted
    // immediately as the response would be 401 anyways.
    return;
}

HashMap<String, String> headers = new HashMap<>();
headers.put("authorization", "Bearer " + accessToken);

// Submit the request with the headers...

Logout

To log out the user from the current app session, you need to invoke thelogoutfunction.

class MyAwesomeViewModel extends AndroidViewModel {
    // Other methods

    // This is called when logout button is clicked.
    public void logout() {
        MyAwesomeApplication app = getApplication();
        app.getAuthgear().logout(new OnLogoutListener() {
            @Override
            public void onLogout() {
                // Logout successfully
            }

            @Override
            public void onLogoutFailed(@NonNull Throwable throwable) {
                // Failed to logout
            }
        });
    }
}

Next steps

To protect your application server from unauthorized access. You will need to integrate your backend with Authgear.

Android SDK Reference

Footnote

Ionic SDK

Guide on how to use Authgear in an Ionic project

In this post, you'll learn how to use Authgear with your Ionic project using the Authgear Ionic SDK.

Objectives (What we'll build)

At the end of this tutorial, we'll build an Ionic app that can do the following:

  • Allow users to log in to their account on your Authgear project

  • Allow new users to sign up

  • Allow signed-in users to view their user info and logout.

The final UI for the app we'll build should look like this:

Pre-requisites

To follow this guide seamlessly, make sure to have the following:

  • Node.js installed on your local machine

  • Android Studio (for building the Android client of your application)

  • X-code (for building the iOS client of your application)

  • Any code editor (VS Code, Sublime, etc)

Now let us get into the steps for using Authgear in an Ionic project.

Part 1: Configure your Authgear Application

In this part, you'll learn how to configure an Authgear application so that you can use it in your Ionic project. You'll do this by performing the following steps in the Authgear Portal.

Step 1: Set up an Authgear Application

In your project, navigate to the Applications section then click on Add Application to create a new Authgear application. Enter a name for your application and select Native App as the Application Type. Next, click Save to continue to the configuration page for your new application.

Step 2: Add Authorized Redirect URIs

In this step, you'll set up authorized redirect URIs for your application. An authorized redirect URI should be a URI pointing to a page on your Ionic app where you want to redirect users at the end of the authorization flow.

To add a URI, scroll to the URIs section of your application configuration page and enter the URI in the text field. You can click the Add URI button to add additional URIs.

For our example app, add the following URIs:

  • com.authgear.example.capacitor://host/path

  • capacitor://localhost

  • http://localhost:8100/oauth-redirect

  • https://localhost

Once you're done, click on the Save button.

Part 2: Implement Ionic App

Now that we have our Authgear application configured, we can now proceed with creating the Ionic application that will have all the features stated in our objective earlier.

For this tutorial, we'll be implementing an Ionic app using React.

Step 1: Create Ionic Project

Before you can create an Ionic project, install the Ionic CLI on your computer by running the following command in Terminal or Command Prompt:

npm install -g @ionic/cli native-run cordova-res

Now create a new Ionic project by running the following command:

ionic start authgear-ionic-example --type=react --capacitor

After running the above command, follow the wizard to create a new blank project.

Next, open your new project in a code editor and update for appId in capacitor.config.ts to the following value:

appId: 'com.authgear.example.capacitor',

This new value for appId is the same value we used in the authorized redirect URI earlier.

Note: It is important that you update the value for appId before you create the Android and iOS projects for your Ionic application. Doing this will enable Capacitor to create your Android and iOS project with the value for appId as the package name and app ID.

You can run the ionic serve command to preview your new blank project on a browser.

Finally, create the Android and iOS projects for your app by running the following commands from your Ionic project's root folder:

First, install the Android and iOS platforms:

npm i @capacitor/android @capacitor/ios

Then, create the projects:

npx cap add android
npx cap add ios

Step 2: Install Authgear SDK

In this step, you'll install the Authgear SDK for Ionic (Capacitor) and the Javascript SDK for the web. The web SDK will help you test your application on a web browser.

To install the SDKs, run the following commands in your Terminal or Command Prompt:

Authgear Ionic SDK

npm i @authgear/capacitor

Authgear Web SDK

npm i @authgear/web

Step 3: Configure Authgear SDK

In this step, you'll learn how to configure your Ionic project using the details from your Authgear application configuration.

To get started, open src/pages/Home.tsx in your code editor and import the Authgear SDK by adding the following code to the top of the file:

import authgearWeb, {
  SessionState,
  CancelError as WebCancelError,
  UserInfo,
} from "@authgear/web";
import authgearCapacitor, {
  CancelError as CapacitorCancelError,
} from "@authgear/capacitor";

The above code imports all the components of the Authgear SDK we need for our example app.

Because Ionic apps can run on the web and native mobile platforms, we have to import both Authgear web and Authgear Capacitor SDKs.

Next, add the following constants to Home.tsx just below the last import statement:

const CLIENT_ID = "";
const ENDPOINT = "";
const REDIRECT_URI_WEB_AUTHENTICATE = "http://localhost:8100/oauth-redirect";
const REDIRECT_URI_CAPACITOR = "com.authgear.example.capacitor://host/path";
const REDIRECT_URI_WEB_REAUTH = "http://localhost:8100/reauth-redirect";

Update the values for the constants (CLIENT_ID, ENDPOINT) you just added to the correct values from your application's configuration page in the Authgear Portal.

Also, add this small utility function that will help to check whether your Ionic app is running natively or on a web browser:

function isPlatformWeb(): boolean {
  return Capacitor.getPlatform() === "web";
}

Now implement a new AuthenticationScreen component in Home.tsx by pasting the following code:

function AuthenticationScreen() {

  const [isAlertOpen, setIsAlertOpen] = useState(false);
  const [alertHeader, setAlertHeader] = useState("");
  const [alertMessage, setAlertMessage] = useState("");

  const [loading, setLoading] = useState(false);
  const [initialized, setInitialized] = useState(false);

  const showError = useCallback((e: any) => {
    const json = JSON.parse(JSON.stringify(e));
    json["constructor.name"] = e?.constructor?.name;
    json["message"] = e?.message;
    let message = JSON.stringify(json);

    if (e instanceof WebCancelError || e instanceof CapacitorCancelError) {
      // Cancel is not an error actually.
      return;
    }

    setIsAlertOpen(true);
    setAlertHeader("Error");
    setAlertMessage(message);
  }, []);

  const postConfigure = useCallback(async () => {
    const sessionState = isPlatformWeb()
      ? authgearWeb.sessionState
      : authgearCapacitor.sessionState;
    if (sessionState !== "AUTHENTICATED") {
      setInitialized(true);
      return;
    }

    if (isPlatformWeb()) {
      await authgearWeb.fetchUserInfo();
    } else {
      await authgearCapacitor.fetchUserInfo();
    }

    setInitialized(true);
  }, []);

  const configure = useCallback(async () => {
    setLoading(true);
    try {

      if (isPlatformWeb()) {
        await authgearWeb.configure({
          clientID: CLIENT_ID,
          endpoint: ENDPOINT,
          sessionType: "refresh_token",
          isSSOEnabled: false,
        });
      } else {
        await authgearCapacitor.configure({
          clientID: CLIENT_ID,
          endpoint: ENDPOINT
        });
      }
      await postConfigure();
    } catch (e) {
      showError(e);
    } finally {
      setLoading(false);
    }
  }, [
    CLIENT_ID,
    ENDPOINT
  ]);
}

Step 4: Start Authentication

Here, we'll implement an authenticate() method inside the AuthenticationScreen component we created in the previous step.

To do this, first, add the following constants that the method will depend on to the top of AuthenticationScreen component:

const [page, setPage] = useState("");

const [sessionState, setSessionState] = useState<SessionState | null>(() => {
  if (isPlatformWeb()) {
    return authgearWeb.sessionState;
  }
  return authgearCapacitor.sessionState;
});

const loggedIn = sessionState === "AUTHENTICATED";

Then, add the authenticate() method by pasting the following code to the end of the AuthenticationScreen component:

const authenticate = useCallback(async (page: string) => {
    setLoading(true);
    try {
      if (isPlatformWeb()) {
        authgearWeb.startAuthentication({
          redirectURI: REDIRECT_URI_WEB_AUTHENTICATE,
          page: page,
        });
      } else {
        const result = await authgearCapacitor.authenticate({
          redirectURI: REDIRECT_URI_CAPACITOR,
          page: page,
        });
        showUserInfo(result.userInfo);
      }
    } catch (e) {
      showError(e);
    } finally {
      setLoading(false);
    }
  }, [showUserInfo, page]);

Calling this authenticate() method will initialize an authentication flow. The page parameter can be used to specify whether to start the authentication flow on the login page or signup page.

Step 5: Handle Redirect in App

At the end of an authentication flow, your users will be redirected to the URL you specified in redirectURI. In this step, we'll set up the routes and code to process redirects to the URIs.

First, create a new file OAuthRedirect.tsx in src/pages/ and add the following code to it:

import { useCallback, useEffect } from "react";
import authgearWeb from "@authgear/web";
import { useIonRouter } from "@ionic/react";

export default function OAuthRedirect() {
  const router = useIonRouter();

  const finishAuthentication = useCallback(async () => {
    const CLIENT_ID = "";
    const ENDPOINT = "";

    try {
      await authgearWeb.configure({
        clientID: CLIENT_ID,
        endpoint: ENDPOINT,
        sessionType: "refresh_token",
      });
      await authgearWeb.finishAuthentication();
      router.push("/", "root", "replace");
    } catch (e) {
      console.error(e);
    }
  }, [router]);

  useEffect(() => {
    finishAuthentication();
  }, [finishAuthentication]);

  return (
    <div>
      Finishing authentication. Open the inspector to see if there is any error.
    </div>
  );
}

Change the values for CLIENT_ID and ENDPOINT in the above code to the correct value from your Authgear application configuration page.

Now open src/App.tsx and create a new route for OAuthRedirect using the following code:

<Route exact path="/oauth-redirect">
    <OAuthRedirect />
</Route>

Remember to import OAuthRedirect in App.tsx.

To handle redirect in the Android project, add the following code to android/app/src/main/AndroidManifest.xml:

<!-- Authgear SDK -->
<activity
    android:name="com.authgear.capacitor.OAuthRedirectActivity"
    android:launchMode="singleTask"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Configure data to be the exact redirect URI your app uses. -->
        <!-- NOTE: The redirectURI supplied in AuthenticateOptions has to match as well -->
        <data
            android:host="host"
            android:pathPrefix="/path"
            android:scheme="com.authgear.example.capacitor" />
    </intent-filter>
</activity>

Step 6: Implement UI

At this point, you will create the User Interface for the AuthenticationScreen component.

To do that, add the following code to the end of the AuthenticationScreen component method:

const fetchUserInfo = useCallback(async () => {
    setLoading(true);
    try {
      if (isPlatformWeb()) {
        const userInfo = await authgearWeb.fetchUserInfo();
        showUserInfo(userInfo);
      } else {
        const userInfo = await authgearCapacitor.fetchUserInfo();
        showUserInfo(userInfo);
      }
    } catch (e) {
      showError(e);
    } finally {
      setLoading(false);
    }
  }, [showError, showUserInfo]);

  const logout = useCallback(async () => {
    setLoading(true);
    try {
      if (isPlatformWeb()) {
        await authgearWeb.logout({
          redirectURI: window.location.origin + "/",
        });
      } else {
        await authgearCapacitor.logout();
      }
    } catch (e) {
      showError(e);
    } finally {
      setLoading(false);
    }
  }, [showError]);

  // On web, it is more natural to configure automatically if client ID and endpoint are filled in.
  useEffect(() => {
      configure();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const onAlertDismiss = useCallback(
    (_e: IonAlertCustomEvent<OverlayEventDetail>) => {
      setIsAlertOpen(false);
    },
    []
  );

  const onClickAuthenticate = useCallback(
    (e: MouseEvent<HTMLIonButtonElement>, page: string) => {
      e.preventDefault();
      e.stopPropagation();

      authenticate(page);
    },
    [authenticate]
  );

  const onClickFetchUserInfo = useCallback(
    (e: MouseEvent<HTMLIonButtonElement>) => {
      e.preventDefault();
      e.stopPropagation();

      fetchUserInfo();
    },
    [fetchUserInfo]
  );

  const onClickLogout = useCallback(
    (e: MouseEvent<HTMLIonButtonElement>) => {
      e.preventDefault();
      e.stopPropagation();

      logout();
    },
    [logout]
  );

  return (
    <>
    <IonAlert
        isOpen={isAlertOpen}
        header={alertHeader}
        message={alertMessage}
        onIonAlertDidDismiss={onAlertDismiss}
      />
    <div className="container">
        <h1>
          Welcome
        </h1>
        <p>Tap any of the buttons to below to login or signup</p>
        <IonButton
          className="button"
          disabled={!initialized || loading || loggedIn}
          onClick={
            (event) => {
              setPage("signup");
              onClickAuthenticate(event, "login")
            }
          }
        >
          Login
        </IonButton>
        <IonButton
          className="button"
          disabled={!initialized || loading || loggedIn}
          onClick={(event) => {
            onClickAuthenticate(event, "signup")
          }}
        >
          Signup
        </IonButton>

        <IonButton
          className="button"
          disabled={!initialized || loading || !loggedIn}
          onClick={onClickFetchUserInfo}
        >
          Fetch User Info
        </IonButton>

        <IonButton
          className="button"
          disabled={!initialized || loading || !loggedIn}
          onClick={onClickLogout}
        >
          Logout
        </IonButton>
        
      </div>
    </>
  );

Step 7: Deploy app to mobile

To deploy your app to a mobile device (for example Android) run the following commands:

First build your project by running:

npm run build

Then sync the changes to the mobile project using this command:

npx cap sync

You can run the project by opening the android project folder in Android Studio or ios folder in X-code.

You can quickly open the project in Android Studio using the following command:

npx cap open android

Once your project builds successfully, you can try the Login, Signup, Fetch User Info, and Logout buttons.

Conclusion

Xamarin SDK

How to integrate with a Xamarin app

This guide provides instructions on integrating Authgear with a Xamarin app. Supported packages include:

  • Xamarin.Essentials 1.7.2 or higher

  • Xamarin.Forms 5.0.0.2401 or higher

Setup Application in Authgear

From the Project listing, create a new Project or select an existing Project. After that, we will need to create an application in the project.

Create a Xamarin app

  • Open Visual Studio

  • Create a new project

  • Choose the Xamarin.Forms template

Install the SDK

  • Authgear.Xamarin targets MonoAndroid 12.0 on Android, and Xamarin.iOS10 on iOS. Update the target framework of the Android and iOS projects to match Authgear.Xamarin's target frameworks.

  • Update Android and iOS project's Xamarin.Essentials to 1.7.2.

Platform Integration

To finish the integration, setup the app to handle the redirectURI specified in the application. This part requires platform specific integration.

Android

Define your own callback activity

using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;
using Authgear.Xamarin;
using Xamarin.Forms;

namespace MyApp.Droid
{
    [Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
    [IntentFilter(new[] { Android.Content.Intent.ActionView },
        Categories = new[] { Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryBrowsable },
        DataScheme = "com.myapp.example")]
    public class WebAuthenticationCallbackActivity : Xamarin.Essentials.WebAuthenticatorCallbackActivity
    {
    }
}

Targeting API level 30 or above (Android 11 or above)

If your Android app is targeting API level 30 or above (Android 11 or above), you need to add a queries section to AndroidManifest.xml.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <!-- Other elements such <application> -->
  <queries>
    <intent>
      <action android:name="android.support.customtabs.action.CustomTabsService" />
    </intent>
  </queries>
</manifest>

Initialize a global AuthgearSdk instance

In your MainActivity.cs

using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;

using Xamarin.Forms;
using Authgear.Xamarin;

namespace MyApp.Droid
{
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            // ...

            var authgear = new AuthgearSdk(this, new AuthgearOptions
            {
                ClientId = CLIENT_ID,
                AuthgearEndpoint = ENDPOINT
            });
            DependencyService.RegisterSingleton<AuthgearSdk>(authgear);
            LoadApplication(new App());

            // ...
        }

        // other methods are omitted for brevity.
    }
}

iOS

Add the following key-value pair in your iOS project Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <!-- other entries ... -->
        <key>CFBundleURLTypes</key>
        <array>
          <dict>
            <key>CFBundleURLName</key>
            <string>com.myapp.example://host/path</string>

            <key>CFBundleURLSchemes</key>
            <array>
              <string>com.myapp.example</string>
            </array>

            <key>CFBundleTypeRole</key>
            <string>Editor</string>
          </dict>
        </array>
</dict>
</plist>

Initialize a global AuthgearSdk instance

In your AppDelegate.cs

using Xamarin.Essentials;
using Xamarin.Forms;
using Authgear.Xamarin;

namespace MyApp.iOS
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            var authgear = new AuthgearSdk(app, new AuthgearOptions
            {
                ClientId = CLIENT_ID,
                AuthgearEndpoint = ENDPOINT
            });
            DependencyService.RegisterSingleton<AuthgearSdk>(authgear);
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }

        public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
        {
            return Xamarin.Essentials.Platform.OpenUrl(app, url, options);
        }

        public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, UIApplicationRestorationHandler completionHandler)
        {
            if (Xamarin.Essentials.Platform.ContinueUserActivity(application, userActivity, completionHandler))
                return true;
            return base.ContinueUserActivity(application, userActivity, completionHandler);
        }
    }
}

Try authenticate

Edit your MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="testauthgear.MainPage">

    <StackLayout>
        <Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
            <Label Text="Welcome to Xamarin.Forms!" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
        </Frame>
        <Button Text="Configure" Clicked="Configure_Clicked" />
        <Button Text="Authenticate" Clicked="Authenticate_Clicked"/>
    </StackLayout>

</ContentPage>

Edit your MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Authgear.Xamarin;

namespace MyApp
{
    public partial class MainPage : ContentPage
    {
        private AuthgearSdk authgear;


        public MainPage()
        {
            InitializeComponent();
            authgear = DependencyService.Get<AuthgearSdk>();
        }

        async void Configure_Clicked(object sender, EventArgs e)
        {
            // You must configure the instance before use.
            // Typically you should do this once on app launch.
            await authgear.ConfigureAsync();
        }

        async void Authenticate_Clicked(object sender, EventArgs e)
        {
            var userInfo = await authgear.AuthenticateAsync(new AuthenticateOptions
            {
                RedirectUri = REDIRECT_URI
            });
        }
    }
}

Get the Logged In State

When you start launching the application. You may want to know if the user has logged in. (e.g. Show users the login page if they haven't logged in). The SessionState reflects the user logged in state in the SDK locally on the device. That means even the SessionState is Authenticated, the session may be invalid if it is revoked remotely. After initializing the Authgear SDK, call FetchUserInfoAsync to update the SessionState as soon as it is proper to do so.

// value can be NoSession or Authenticated
// After Authgear.ConfigureAsync, it only reflects local state.
var sessionState = authgear.SessionState;

if (sessionState == SessionState.Authenticated)
{
    try
    {
        var userInfo = await authgear.FetchUserInfoAsync();
        // sessionState is now up to date
    }
    catch (Exception ex)
    {
        // sessionState is now up to date
        // it will change to NoSession if the session is invalid
    }
}

The value of SessionState can be Unknown, NoSession or Authenticated. Initially, the SessionState is Unknown. After a call to authgear.configure, the session state would become Authenticated if a previous session was found, or NoSession if such session was not found.

Fetching User Info

Logout

To log out the user from the current app session, you need to invoke thelogoutfunction.

await authgear.LogoutAsync();

Calling An API

To include the access token to the HTTP requests to your application server, you set the bearer token manually by using authgear.AccessToken.

Using HttpClient

You can get the access token through authgear.AccessToken. Call RefreshAccessTokenIfNeededAsync every time before using the access token, the function will check and make the network call only if the access token has expired. Then, include the access token into the Authorization header of the http request.

await authgear.RefreshAccessTokenIfNeededAsync();
// Access token is ready to use
// AccessToken can be string or undefined
// It will be empty if user is not logged in or session is invalid
var accessToken = authgear.AccessToken;
var client = GetHttpClient();  // Get the re-used http client of your app, as per recommendation.
var httpRequestMessage = new HttpRequestMessage(myHttpMethod, myUrl);
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

Next steps

To protect your application server from unauthorized access. You will need to integrate your backend with Authgear.

Xamarin SDK Reference

Footnote

ASP.NET Core MVC

Add authentication for ASP.NET app with Authgear

Learning objectives

You will learn the following throughout the article:

Prerequisites

Before you get started, you will need the following:

Part 1: Configure Authgear

Step 1: Configure an application

Use the interactive selector to create a new Authgear OIDC Client application or select an existing application that represents the project you want to integrate with.

Step 2: Configure Redirect URI

Step 3: Enable Access Token

Also, enable Issue JWT as an access token option under the Access Token section of the app configuration:

Step 4: Choose a Login method

After you create the Authgear app, you choose how users need to authenticate on the login page. From the Authentication tab, navigate to Login Methods, you can choose a login method from various options including, by email, mobile, or social, just using a username or the custom method you specify. For this demo, we choose the Email+Passwordless approach where our users are asked to register an account and log in by using their emails. They will receive a One-time password (OTP) to their emails and verify the code to use the app.

Step 1: Install dependencies

Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect

Step 2: Install and configure OpenID Connect Middleware

public class Startup
 {

     public IWebHostEnvironment Environment { get; }
     public IConfiguration Configuration { get; }

     public Startup(IWebHostEnvironment environment, IConfiguration config)
     {
         Environment = environment;
         Configuration = config;
     }

     // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
     public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
     {
         app.UseRouting();
         app.UseAuthentication();
         app.UseAuthorization();
         app.UseEndpoints(endpoints =>
         {
             endpoints.MapRazorPages();
         });
     }

     public void ConfigureServices(IServiceCollection services)
     {
         // Prevent WS-Federation claim names being written to tokens
         JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

         services.AddAuthentication(options =>
         {
             options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
             options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
         })
         .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
         {
             // Use the strongest setting in production, which also enables HTTP on developer workstations
             options.Cookie.SameSite = SameSiteMode.Strict;
         })
         .AddOpenIdConnect(options =>
         {

             // Use the same settings for temporary cookies
             options.NonceCookie.SameSite = SameSiteMode.Strict;
             options.CorrelationCookie.SameSite = SameSiteMode.Strict;

             // Set the main OpenID Connect settings
             options.Authority = Configuration.GetValue<string>("OpenIdConnect:Issuer");
             options.ClientId = Configuration.GetValue<string>("OpenIdConnect:ClientId");
             options.ClientSecret = Configuration.GetValue<string>("OpenIdConnect:ClientSecret");
             options.ResponseType = OpenIdConnectResponseType.Code;
             options.ResponseMode = OpenIdConnectResponseMode.Query;
             string scopeString = Configuration.GetValue<string>("OpenIDConnect:Scope");
             options.Scope.Clear();
             scopeString.Split(" ", StringSplitOptions.TrimEntries).ToList().ForEach(scope =>
             {
                 options.Scope.Add(scope);
             });

             // If required, override the issuer and audience used to validate ID tokens
             options.TokenValidationParameters = new TokenValidationParameters
             {
                 ValidIssuer = options.Authority,
                 ValidAudience = options.ClientId
             };

             // This example gets user information for display from the user info endpoint
             options.GetClaimsFromUserInfoEndpoint = true;

             // Handle the post logout redirect URI
             options.Events.OnRedirectToIdentityProviderForSignOut = (context) =>
             {
                 context.ProtocolMessage.PostLogoutRedirectUri = Configuration.GetValue<string>("OpenIdConnect:PostLogoutRedirectUri");
                 return Task.CompletedTask;
             };

             // Save tokens issued to encrypted cookies
             options.SaveTokens = true;

             // Set this in developer setups if the OpenID Provider uses plain HTTP
             options.RequireHttpsMetadata = false;
         });

         services.AddAuthorization();
         services.AddRazorPages();

         // Add this app's types to dependency injection
         services.AddSingleton<TokenClient>();
     }
 }

Step 3: Add Protected resource

Assume that there is a protected resource like a Razor page Protected.cshtml that is used to represent views:

@page "/protected"
@model ProtectedModel

@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers

<style type="text/css">
button
{
  width: 200px;
}
</style>

<h1>Protected View</h1>

<h3>
    <p>Welcome: @Model.Username</a>
    <p>Current Access Token: @Model.AccessToken</a>
    <p>Current Refresh Token: @Model.RefreshToken</a>
    
    <form method="post">
        <p><button value="RefreshToken" asp-page-handler="RefreshToken">Refresh Token</button></p>
        <p><button value="Logout" asp-page-handler="Logout">Logout</button></p>
    </form>
</h3>

And ProtectedModel.cs class to which Authorize the attribute is applied requires authorization.

[Authorize]
public class ProtectedModel : PageModel
{
    public string Username { get; set; }
    public string AccessToken { get; set; }
    public string RefreshToken { get; set; }

    private readonly TokenClient tokenClient;

    public ProtectedModel(TokenClient tokenClient)
    {
        this.tokenClient = tokenClient;
    }

    public async Task OnGet()
    {
        ClaimsPrincipal user = this.User;
        var givenName = user.FindFirstValue("given_name");
        var familyName = user.FindFirstValue("family_name");
        this.Username = $"{givenName} {familyName}";

        this.AccessToken = await this.tokenClient.GetAccessToken(this.HttpContext);
        this.RefreshToken = await this.tokenClient.GetRefreshToken(this.HttpContext);
    }

    public async Task<IActionResult> OnPostRefreshToken()
    {
        await this.tokenClient.RefreshAccessToken(this.HttpContext);
        this.AccessToken = await this.tokenClient.GetAccessToken(this.HttpContext);
        this.RefreshToken = await this.tokenClient.GetRefreshToken(this.HttpContext);
        return Page();
    }

    public async Task OnPostLogout()
    {
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
    }
}

To see protected data, users need to go through the authentication process via Authgear.

If a user has not authenticated yet, Unauthenticated.chtml the page is rendered, an OpenID Connect redirect flow is triggered and the user needs to authenticate through the Authgear login page. See Run the Application section

After successful authentication, you should see the protected page with the following details:

Step 4: Get and Use Refresh Token

As part of the OAuth 2.0 standard, we can use the refresh token returned by the token endpoint to get a new access token. Doing so enables our application to replace an expired access token without requiring the user to repeat the entire login process.

The following code in ProtectedModel.cs is responsible for doing that:

public async Task<IActionResult> OnPostRefreshToken()
{
    await this.tokenClient.RefreshAccessToken(this.HttpContext);
    this.AccessToken = await this.tokenClient.GetAccessToken(this.HttpContext);
    this.RefreshToken = await this.tokenClient.GetRefreshToken(this.HttpContext);
    return Page();
}

Note: You must include offline_access in your OAuth 2.0 scope for the Authgear authorization server to return a refresh token.

Step 5: Logout

The Logout button on the Protected.cshtml page calls the OnPostLogout() method in ProtectedModel.cs. The method will delete the current user session and redirect to Authgear's end session endpoint for the user to complete the logout process.

The code sample below shows the implementation of the OnPostLogout() method:

public async Task OnPostLogout()
    {
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
    }

Step 6: Set up and run the application

Start by cloning the project into your local machine:

git clone 

Make the project directory your current working directory:

cd authgear-example-dotnet

Update the following configuration variables in the appsettings.json file with your Authgear app settings values from Part1 such as Issuer, ClientId, ClientSecret, and Authgear endpoint:

{
    "OpenIDConnect": {
        "ClientId": "{your-client-id}",
        "ClientSecret": "{your-client-secret}",
        "Issuer": "{your-authgear-app-endpoint}",
        "Scope": "openid offline_access",
        "PostLogoutRedirectUri": "<http://localhost:5002>",
        "TokenEndpoint": "{your-authgear-app-endpoint}/oauth2/token"
    },
    "Urls": "<http://localhost:5002>",
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    }
}
dotnet build
dotnet run

After you have authenticated, a protected view is rendered. The application receives an Access token that it uses to present user data on the screen, and tokens that could be used in upstream requests to some backend API, to access data on behalf of the user.

Next steps

This guide showed how to quickly implement an end-to-end OpenID Connect flow in .NET with Authgear. Only simple code is needed, after which protected views are secured with built-in UI login pages.

Regular Web App

Traditional web app that runs on the server

Java Spring Boot

Authentication for Spring Boot App with Authgear and OAuth2

Learning objectives

You will learn the following:

  • How to create an app on Authgear.

  • How to enable Email based login.

  • Add sign-up and login features to Spring Boot App.

Prerequisites

Before you get started, you will need the following:

  • Java 17 or higher.

Add login to your Spring Webapp

Part 1: Configure Authgear

Step 1: Configure an application

Use the interactive selector to create a new Authgear OIDC Client application or select an existing application that represents the project you want to integrate with.

Step 2: Configure Redirect URI

A Redirect URI is a URL in your application that you would like Authgear to redirect users to after they have authenticated. In our case, it will be a home page for our Spring Boot App. If not set, users will not be returned to your application after they log in.

To follow the example in this post, add the following URL as a redirect URI:

http://localhost:8080/login/oauth2/code/authgear

Step 3: Choose a Login method

After you create the Authgear app, you choose how users need to authenticate on the login page. From the “Authentication” tab, navigate to “Login Methods”, you can choose a login method from various options including by email, mobile, or social, just using a username or the custom method you specify. For this demo, we choose the Email+Passwordless approach where our users are asked to register an account and log in by using their emails. They will receive a One-time password (OTP) to their emails and verify the code to use the app.

Part 2: Configure Spring Boot application

Step 1: Add Spring dependencies


  <dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-oauth2-client</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
      <dependency>
          <groupId>org.thymeleaf.extras</groupId>
          <artifactId>thymeleaf-extras-springsecurity6</artifactId>
          <version>3.1.1.RELEASE</version>
      </dependency>
  </dependencies>
  

Step 2: Configure OIDC authentication with Authgear

Spring Security makes it easy to configure your application for authentication with OIDC providers such as Authgear. We need to add the client credentials to the application.properties file with your Auhgear provider configuration. You can use the sample below and replace properties with the values from your Authgear app:


spring.security.oauth2.client.registration.authgear.client-id={your-client-id}
spring.security.oauth2.client.registration.authgear.client-secret={your-client-secret}
spring.security.oauth2.client.registration.authgear.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.authgear.scope=openid,offline_access
spring.security.oauth2.client.registration.authgear.redirect-uri=http://localhost:8080/login/oauth2/code/authgear/
spring.security.oauth2.client.provider.authgear.token-uri=https://{DOMAIN}/oauth2/token
spring.security.oauth2.client.provider.authgear.authorization-uri=https://{DOMAIN}/oauth2/authorize

# To logout from the app
authgear.oauth2.end-session-endpoint=https://{DOMAIN}/oauth2/end_session
  

Step 3: Add login to your application

To enable user login with Authgear, create a class that will provide an instance of SecurityFilterChain, add the @EnableMethodSecurity annotation, and override the necessary method:


@Configuration
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {

    @Value("${authgear.oauth2.end-session-endpoint}")
    private String endSessionEndpoint;

    @Bean
    public SecurityFilterChain configure(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) -> requests
                // allow anonymous access to the root page
                .requestMatchers("/").permitAll()
                // authenticate all other requests
                .anyRequest().authenticated())
            // enable OAuth2/OIDC
            .oauth2Login(withDefaults())
            // configure logout handler
            .logout(logout -> logout.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/")
                .addLogoutHandler(oidcLogoutHandler()));
        return http.build();
    }

    LogoutHandler oidcLogoutHandler() {
        return (request, response, authentication) -> {
            try {
                response.sendRedirect(endSessionEndpoint);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        };
    }
}
  

Step 4: Add the front page

We create a simple home.html page using Thymeleaf templates. When a user opens the page running on http://localhost:8080/, we show the page with buttons for login or logout:

Step 5: Add controller

Next, we create a controller class to handle the incoming request. This controller renders the home.html page. When the user authenticates, the application retrieves the user's profile information attributes to render the page.


@Controller
public class HomeController {
    @GetMapping("/")
    String home() {
        return "home";
    }
}
  

Step 6: Run the Application

To run the application, you can execute the mvn spring-boot:run goal. Or run from your editor the main ExampleApplication.java file. The sample application will be available at http://localhost:8080/.

Click on the Login button to be redirected to the Authgear login page.

You can also customize the login page UI view from the Authgear Portal. After you sign up, you will receive an OTP code in your email to verify your identity.

And log into your new account, you will be redirected back to the home page:

Next steps

Backend/API

An API or service protected by Authgear

If your API or backend service needs authentication, you can validate the JWT token in your application server code.

PHP

Authentication for PHP websites with Authgear and OAuth2

Using OAuth, you can use Authgear to add user authentication in a vanilla PHP application.

In this guide, we'll cover how to implement OAuth 2.0 login in a regular PHP web application with Authgear as the Identity Provider.

What You Will Learn

At the end of this post, you'll learn the following:

  • How to create an Authgear Application

  • How to enable email and password sign-in

  • How to sign in with Authgear from a PHP app

  • How to request user info from Authgear

  • How to use a refresh token

  • And finally how to log users out and revoke access tokens.

Pre-requisites

To follow along, you'll need the following:

  • PHP runtime (E.g XAMPP for testing offline on Windows devices)

  • Your preferred code editor (e.g VS Code).

What We Will Build

In this guide, we'll build a basic PHP application that lets a user sign in with their registered email and password.

The application will welcome the user with their email address after they sign in successfully. If the user is not signed in, the application will display links to Register or Login.

The following screenshot shows what the User Interface for the app will look like:

How to Add User Authentication to PHP with Authgear

Now let's dive into the actual steps of how to add Authgear to a PHP application.

Part 1: Configure an Authgear Application

Under this section, we will cover the steps for configuring the Authgear application our PHP website will be connecting to. We'll do all these configurations in the Authgear Portal.

Step 1: Set up Authgear Application

To do that, log in to the Authgear Portal, and select your project (or create a new one if you don't have any yet). From your project dashboard navigate to the Applications section and enter the details for your new application as shown below:

Once you're done, click on the Save button to continue. Then, click on Next to see the configuration page for your application.

The application configuration page contains basic information like Client ID and Client Secret that we'll use later in this tutorial. Hence, try to note the values down.

In addition to basic information, you can find other configuration information including endpoints and Authorized Redirect URIs.

Step 2: Authorized Redirect URIs

The Authorized Redirect URIs section contains a link to the page you want Authgear to redirect users to after login.

Update the value for Authorized Redirect URIs to a page on your application. For our example PHP application the value will be http://localhost because we plan to test run it offline using XAMPP. Also, try to note this value down as we'll be using it in later steps.

Part 2: Implement PHP Project

Here we will cover the steps for implementing a PHP website that interacts with Authgear using the Open ID Connect (OIDC) standard.

Step 1: Create a PHP Project

Create a new PHP project on your computer and add an index.php file to the root of the project folder.

Add the following code to index.php to create the User Interface of the example app.

Note: The Login and Logout links in the above code currently point to login.php and logout.php respectively, we'll create both files later.

Step 2: Add Authgear Configuration to PHP Project

In this step, we'll add our Authgear application configuration to the PHP project.

Install the package manually from Github or via Composer by running the following command from your PHP project's root directory:

Next, after the package is installed, create a new config.php file in the PHP project folder. Add the following code to the file:

Note: Replace the values for clientId, clientSecret, redirectUri with corresponding values from the Authgear application you created in Step 1.

Including the offline_access scope is required to get a refresh token from Authgear.

Step 3: Add Login Authorization

The flow for Login on our app is as follows:

  1. The user clicks on the Login button

  2. User is redirected to the Authgear authorization page where they can sign in using email and password or any other sign-in methods you have enabled for your Authgear project.

  3. The user is redirected back to your website with an authorization code.

In order to implement the above, you need to create a login.php file in your project's root directory. Add the following code to the login.php file:

At this point, if you try running the example app in a browser and click the Login link in index.php, your app should redirect to the Authgear login page. If you sign in successfully, you should be redirected back to the redirect URL you specified earlier in your project configuration.

Authgear will redirect to your Authorized Redirect URI with extra parameters like code or an error message in the URL. The value for the code parameter is your authorization code. In the next step, we'll use the authorization code to generate an access token.

Step 4: Get Access Token and Request User Info

Usually, after successful sign-in, you'll want to start using the current user's info to offer custom experience in your app.

In this step, we'll use the PHP OAuth 2.0 Client once more to interact with our Authgear app.

First, open index.php and search for the line with the following code:

Replace the above line with this code:

The above code exchanges the authorization code returned in the redirect for an access token. It then stores the access token in the PHP session so that we can use this token in future requests to protected resources.

Now that we have the access token, let's try to get the current user's details. To do that, update the HTML part in index.php like this:

Now test the app on your browser again and you should get the following page after login:

We've successfully added user authentication to our PHP app using Authgear as the identity provider. The above page displays a welcome message with the email address the user registered with on your Authgear project. You can display other info about the user from the value of $userInfo variable.

Step 5: Getting and Using a Refresh Token

In OAuth 2.0, a refresh token is a key that's usually included in the response from the token endpoint when a client application exchanges the authorization code for an access token.

Access tokens expire after some time. Hence, we can use this refresh token to request a new access token without requiring our application users to log in again. In this step, we'll show you how to use the refresh token.

In the last step, we stored the value for the refresh token in the $_SESSION['refreshToken'] variable. So, to get the refresh token, simply read the value from that variable.

Now, add the following code to index.php to read and use the refresh token to get a new access token:

First, find the line with the following code:

Replace that line with the following blocks of code:

Note: It is required to include offline_access in your OAuth 2.0 scopes to get a refresh token from Authgear.

Step 6: Logout

Authgear provides a token revoke endpoint that you can use to revoke a refresh token and all the access associated with it.

To use the token revoke endpoint to log users out of your application, create a new logout.php file in your project directory then add the following code to the file:

The above code will revoke your refresh token and delete all the session variables.

Summary

In this post, we covered how to get started with adding Authgear to a regular web app built with PHP and no framework.

We also tried out an example of using the Authgear authorization code to retrieve an access token, then we used the token to access the user info endpoint.

Python Flask App

Authentication for a Python web application

Learning objectives

You will learn the following:

  • How to create an app on Authgear.

  • How to enable Email-based login.

  • Add sign-up and login features to the Flask app.

Prerequisites

Before you begin, you'll need the following:

Part 1: Configure Authgear

Step 1: Configure an application

Every application in Authgear is assigned an alphanumeric, unique client ID that your application code will use to call Authgear APIs through the Authlib client library in the Flask app. Record the generated Authgear Issuer Domain (for example, example-auth.authgear-apps.com), CLIENT ID, CLIENT SECRET from the output. You will use these values in Part 2 for the Flask app config.

Step 2: Configure Redirect URI

Step 3: Choose a Login method

After you create the Authgear app, you choose how users need to authenticate on the login page. From the Authentication tab, navigate to Login Methods, you can choose a login method from various options including, by email, mobile, or social, just using a username or the custom method you specify. For this demo, we choose the Email+Passwordless approach where our users are asked to register an account and log in by using their emails. They will receive a One-time password (OTP) to their emails and verify the code to use the app.

Part 2: Create a Flask application

Next, create a Flask application with a single page and routes for home, callback, login, and logout flows.

Step 1: Configure an .env file

Start with creating a requirements.txt file in your project directory:

Run pip install -r requirements.txt from your command-line interface to make these dependencies available to the Python project.

Step 2: Setup the application

Create a server.py file in the project directory that contains application logic. Add the necessary libraries the application uses.

Load the configuration .env file to use values such as AUTHGEAR_CLIENT_ID AUTHGEAR_CLIENT_SECRET, AUTHGEAR_DOMAIN and APP_SECRET_KEY in the app.

Configure Authlib to handle the application's authentication with Authgear based on OIDC:

Step 3: Setup the application routes

When visitors to the app visit the /login route, they'll be redirected to Authgear to begin the authentication flow.

Once users complete the login process using Authgear, they will be redirected back to the application's /callback route. This route ensures that the user's session is saved, so they won't need to log in again during subsequent visits.

Refresh Token

Calling the authorize_access_token() method of the Flask Authlib package will include a refresh token in the token response, provided your Flask application has offline_access as one of the OAuth 2.0 scopes.

Authlib will also use the refresh token to obtain a new access token automatically when the current access token has expired.

Logout

The route /logout manages the user's logout process from the application. It clears the user's session within the app and momentarily redirects to Authgear's logout endpoint to guarantee a thorough session clearance. After this, users are navigated back to your home route (which we'll discuss shortly).

The home route will either display the details of a logged-in user or provide an option for visitors to sign in.

Step 4: Add UI page

Create a new sub-directory in the project folder named templates, and create a file home.html.

Step 5: Run the application

Run the application from the project root directory:

python server.py

Next steps

In this guide, you'll learn how to implement authentication for the application, a popular React-based framework for JavaScript, and as the OIDC provider. The source code can be found on .

In the , the Next.js app is integrated with Authgear, and the client library is used for sending authentication requests as an OpenID Connect middleware from the app to Authgear.

A free Authgear account. if you don't have one already.

.

Experience with framework and application development.

To use Authgear services, you’ll need to have an application set up in the Authgear . This setup allows users in Authgear to sign in to the Next.js application automatically once they are authenticated by Authgear.

To set up the application, navigate to the and select Applications on the left-hand navigation bar. Use the interactive selector to create a new Authgear OIDC Client application or select an existing application that represents the project you want to integrate with.

Every application in Authgear is assigned an alphanumeric, unique client ID that your application code will use to call Authgear APIs through the NextAuth.js Client in the Next.js app. Record the generated Authgear ISSUER (for example, ), CLIENT ID, CLIENT SECRET from the output. You will use these values in the next step for the client app config.

An Authorized Redirect URI of your application is the URL that Authgear will redirect to after the user has authenticated for the OpenID Connect middleware to complete the authentication process. In our case, it will be a home page for our Next.js and it will run at .

Set the following to the Authorized Redirect URIs field. If not set, users will not be returned to your application after they log in.

You have two options here. You can either clone a or build the app from scratch.

If you want to run an already working application, you can clone the demo project from this using the following command.

Either way, continue configuring the to proceed with this tutorial.

Now that you have the application running, let's implement the authentication process by using . We recommend you look also at the for the most up-to-date instructions. First, install NextAuth.js:

Next, you'll configure a for Authgear. Doing so ensures every request to the /api/auth/* path is handled by NextAuth.js.

We've added as the scope to make Authgear return all user profiles

This will make the React Hook accessible to your entire application. Now, create a component that will either render a "Log in" or "Log out" button, depending on the session state, in a src/components/login-button.jsx file.

Browse to . If the installation went successful, you should see the Login page.

Your users can sign-up and login to your application through a page hosted by Authgear, which provides them with a secure, standards-based login experience that you can customize with your own branding and various authentication methods, such as , , , with SMS/WhatsApp, and multi-factor authentication (MFA).

Signup for an Authgear Portal account in . Or you can use your self-deployed Authgear.

Step 1: Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. You will see the "New Application" page or Click ⊕Add Application in the top tool bar.

  3. Input the name of your application and select Native App as the application type. Click "Save".

  4. You will see a list of guides that can help you for setting up, then click "Next".

Create Application

Step 2: Configure the application

  1. In your IDE, define a custom URI scheme that the users will be redirected back to your app after they have authenticated with Authgear, e.g. com.myapp.example://host/path.[^1]

  2. Head back to Authgear Portal, fill in the Redirect URI that you have defined in the previous steps.

  3. Click "Save" in the top tool bar and keep the Client ID. You can also obtain it again from the Applications list later.

oauth:
  clients:
    - name: your_app_name
      client_id: a_random_generated_string
      redirect_uris:
        - "com.myapp.example://host/path"
      grant_types:
        - authorization_code
        - refresh_token
      response_types:
        - code
        - none

In some cases, you may need to obtain current user info through the SDK. (e.g. Display email address in the UI). Use the fetchUserInfo function to obtain the user info, see .

For detailed documentation on the Flutter SDK, visit

[^1]: For futher instruction on setting up custom URI scheme in Flutter, see

[^2]: For more explanation on JWT, see

Signup for an Authgear Portal account in . Or you can use your self-deployed Authgear.

Step 1: Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application and select Native App as the application type. Click "Save".

  4. You will see a list of guides that can help you for setting up, then click "Next".

Create an application

Step 2: Configure the application

  1. In your IDE (e.g. Android Studio), define a custom URI scheme that the users will be redirected back to your app after they have authenticated with Authgear, e.g. com.myapp.example://host/path.[^1]

  2. Head back to Authgear Portal, fill in the Redirect URI that you have defined in the previous steps.

  3. Click "Save" in the top tool bar and keep the Client ID. You can also obtain it again from the Applications list later.

oauth:
  clients:
    - name: your_app_name
      client_id: a_random_generated_string
      redirect_uris:
        - "com.myapp://host/path"
      grant_types:
        - authorization_code
        - refresh_token
      response_types:
        - code
        - none

Add the following code to your app's Application class. If there is none, add a class that extends Application. Make sure it is declared in AndroidManifest.xml's application tag with the name attribute as described .

Add the following code to your view model. Do NOT call these codes in activity as this can lead to memory leak when your activity instance is destroyed. You can read more on the view model in the official documentation .

In some cases, you may need to obtain current user info through the SDK. (e.g. Display email address in the UI). Use the fetchUserInfo function to obtain the user info, see .

Call refreshAccessTokenIfNeeded every time before using the access token, the function will check and make the network call only if the access token has expired. Include the access token into the Authorization header of your application request. If you are using OKHttp in your project, you can also use the interceptor extension provided by the SDK, see .

For detailed documentation on the Flutter SDK, visit

[^1]: For further instruction on setting up custom URI scheme in Android, see [^2]: For more explanation on JWT, see

authgear ionic example app landing page

An Authgear account. You can sign up for one for free .

First, log in to Authgear Portal at and select an existing project or create a new one.

authgear-app-redirect-uris

Authgear Capacitor SDK makes it easier to use Authgear in your Ionic application. It provides many helpful methods and interfaces for interacting with the Authgear service from your Ionic application. To learn more about the SDK check . Also, check out the complete repo for the Authgear Ionic SDK example app .

Signup for an Authgear Portal account in . Or you can use your self-deployed Authgear.

Step 1: Create an application in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name of your application and select Native App as the application type. Click "Save".

  4. You will see a list of guides that can help you for setting up, then click "Next".

Create an application

Step 2: Configure the application

  1. In your IDE (e.g. Visual Studio), define a custom URI scheme that the users will be redirected back to your app after they have authenticated with Authgear, e.g. com.myapp.example://host/path.[^1]

  2. Head back to Authgear Portal, fill in the Redirect URI that you have defined in the previous steps.

  3. Click "Save" in the top tool bar and keep the Client ID. You can also obtain it again from the Applications list later.

oauth:
  clients:
    - name: your_app_name
      client_id: a_random_generated_string
      redirect_uris:
        - "com.myapp.example://host/path"
      grant_types:
        - authorization_code
        - refresh_token
      response_types:
        - code
        - none

Search for "Authgear.Xamarin" on nuget.org and add it to your base project.

In some cases, you may need to obtain current user info through the SDK. (e.g. Display email address in the UI). Use the FetchUserInfoAsync function to obtain the user info, see .

For detailed documentation on the Xamarin SDK, visit

[^1]: For further instruction on setting up custom URI scheme in Xamarin, see [^2]: For more explanation on JWT, see

In this guide, you will learn how to add authentication features with by implementing an flow, then retrieving OAuth tokens, to call APIs. View on GitHub.

How to add user login, sign-up, and logout to Core Applications.

How to use the Core Authorization Middleware to protect Core application routes.

Add authentication to Core App

A free Authgear account. if you don't have one already.

downloaded and installed on your machine. You can also use and to automatically detect the .NET version.

To use Authgear services, you’ll need to have an application set up in the Authgear . The Authgear application is where you will configure how you want to authenticate and manage your users.

Every application in Authgear is assigned an alphanumeric, unique client ID that your application code will use to call Authgear APIs through the OpenID Connect Client in the .NET app. Note down the Authgear ISSUER (for example, ), CLIENT ID, CLIENT SECRET, and OpenID Token Endpoint () from the output. You will use these values in the next step for the client app config.

A Redirect URI of your application is the URL that Authgear will redirect to after the user has authenticated in order for the OpenID Connect middleware to complete the authentication process. In our case, it will be a home page for our and it will run at.

Set the following redirect URI: If not set, users will not be returned to your application after they log in.

Part 2: Configure Core application to use Authgear

This guide will be used to provide a way for your users to log in to your Core application. The can be found on GitHub. If you are familiar with the steps, you can skip this part and clone the code repository and run the code sample by following the file there.

To integrate Authgear with Core you will use both the Cookie and OpenID Connect (OIDC) authentication handlers. If you are not using a sample project and are integrating Authgear into your own existing project, then please make sure that you add Microsoft.AspNetCore.Authentication.OpenIdConnect packages to your application. Run the following command in your terminal or use your editor to include the NuGet package there:

To enable authentication in your Core application, use the OpenID Connect (OIDC) middleware. Open Startup the class and in the ConfigureServices method, add the authentication services and call the AddAuthentication method. To enable cookie authentication, call the AddCookie method. Next, configure the OIDC authentication handler by adding method AddOpenIdConnect implementation. Configure other parameters, such as Issuer, ClientId, ClientSecret , and Scope. Here, is what looks like Startup.cs after you apply these changes:

Execute the following command to run the Core web application:

You can now visit to access the application. When you click on the "View Protected Data" button, Core takes you to the Authgear’s Login page.

Your users can log in to your application through a page hosted by Authgear, which provides them with a secure, standards-based login experience that you can customize with your own branding and various authentication methods, such as , , , with SMS/WhatsApp, and multi-factor authentication (MFA).

If you have a traditional web application like Java EE, Express, PHP, GO, Laravel, or Core MVC and you want to integrate authentication features.

In this guide, you will learn how to add authentication to your Java Spring Boot application using with Authgear as the Identity Provider (IdP).

A free Authgear account. if you don't have one already.

To use Authgear services, you’ll need to have an application set up in the Authgear . The Authgear application is where you will configure how you want authentication to work for the project you are developing.

Every application in Authgear is assigned an alphanumeric, unique client ID that your application code will use to call Authgear APIs through the Spring Boot . Note down the Authgear issuer (for example, https://example-auth.authgear.cloud/), CLIENT ID, CLIENT SECRET, and OpenID endpoints from the output. You will use these values in the next step for the client app config.

To create a new Spring Boot application you use the . Then you add dependencies to pom.xml file such as starter provides all the Spring Security dependencies needed to add authentication to your web application and Thymeleaf is used just to build a single page UI.

You have successfully configured a Spring Boot application to use Authgear for authentication. Now users can sign up for a new account, log in, and log out. The full source code of the examples can be found .

There is so much more you can do with Authgear. Explore other means of login methods such as using in an email, , or . For the current application, you can also from the Authgear portal.

An Authgear account. for free if you don't have an account yet.

(PHP package manager) installation

The first step you need to take is to create a new application or configure an existing application on the Authgear .

We'll use the PHP package for the configuration.

Here's a link complete source code for .

There's so much more you can do with Authgear and you can continue learning by checking out more topics on the .

This guide demonstrates how to add authentication with Authgear to a Python web application built with the framework using the OAuth library. The full source code for this sample project can be found on the .

A free Authgear account. if you don't have one already.

Make sure that 3.10 or above is installed on your machine.

Download and Install to manage project packages.

To use Authgear services, you’ll need to have an application set up in the Authgear . This setup allows users in Authgear to sign in to the Flask application automatically once they are authenticated by Authgear.

To set up the application, navigate to the and select Applications on the left-hand navigation bar. Use the interactive selector to create a new Authgear OIDC Client application or select an existing application that represents the project you want to integrate with.

An Authorized Redirect URI of your application is the URL that Authgear will redirect to after the user has authenticated in the Authgear to complete the authentication process. In our case, it will be a home page for our Flask and it will run at .

Set the following to the Authorized Redirect URIs field. If not set, users will not be returned to your application after they log in.

The application should now be accessible to open from a browser at .

There is so much more you can do with Authgear. Explore other means of login methods such as using in an email, , or . For the current application, you can also from the Authgear portal.

Edit an application

If you wish to , select "Issue JWT as access token".[^2] If you wish to , leave this unchecked. See comparisons in .

Edit an application

If you wish to , turn on "Issue JWT as access token".[^2] If you wish to , leave this unchecked. See comparisons in .

Edit an application

If you wish to , turn on "Issue JWT as access token".[^2] If you wish to , leave this unchecked. See comparisons in .

Next.js
Authgear
GitHub
demo application
NextAuth.js
Sign up
Node.js
Next.js
Dashboard
Authgear Portal UI
https://example-auth.authgear.cloud
http://localhost:3000
http://localhost:3000/api/auth/callback/authgear
working example
GitHub repository
Environment variables
NextAuth.js
NextAuth.js Getting Start guide
custom provider
https://authgear.com/scopes/full-userinfo
useSession()
localhost:3000
social logins
passwordless
biometrics logins
one-time-password (OTP)
https://portal.authgear.com/
validate JSON Web Token (JWT) in your own application server
forward authentication requests to Authgear Resolver Endpoint
Backend Integration
Backend Integration
Flutter SDK Reference
https://docs.flutter.dev/development/ui/navigation/deep-linking
https://en.wikipedia.org/wiki/JSON_Web_Token
https://portal.authgear.com
validate JSON Web Token (JWT) in your own application server
forward authentication requests to Authgear Resolver Endpoint
Backend Integration
here
here
example
detail
Backend Integration
Android SDK Reference
https://developer.android.com/training/app-links/deep-linking
https://en.wikipedia.org/wiki/JSON_Web_Token
here
https://portal.authgear.com/
the SDK Reference
here
https://portal.authgear.com/
validate JSON Web Token (JWT) in your own application server
forward authentication requests to Authgear Resolver Endpoint
Backend Integration
https://www.nuget.org/packages/Authgear.Xamarin/
Backend Integration
Xamarin SDK Reference
https://www.xamarinhelp.com/uri-scheme/
https://en.wikipedia.org/wiki/JSON_Web_Token
Authgear
OpenID Connect
implementation
ASP.NET
ASP.NET
ASP.NET
ASP.NET
Sign up
.NET 7
Visual Studio
VS code
Dashboard
https://example-auth.authgear.cloud
https://example-auth.authgear.cloud/oauth2/token
ASP.NET
http://localhost:5002
http://localhost:5002/signin-oidc
ASP.NET
ASP.NET
project source code
README.md
ASP.NET
ASP.NET
ASP.NET
http://localhost:5002
ASP.NET
social logins
passwordless
biometrics logins
one-time-password (OTP)
ASP.NET
Java Spring Boot
Next.js
ASP.NET Core MVC
Express
Laravel
PHP
Python Flask App
OAuth2
Sign up
Dashboard
OAuth 2 Client
Spring Initializr
spring-boot-starter-oauth2-client
on GitHub
Magic links
social logins
WhatsApp OTP
add more users
<?php
$appUrl = "REPLACE WITH YOUR AUTHGEAR PROJECT URL";
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP Demo - Home</title>
</head>
<body style="background-color: #DEDEDE">
    <div style="max-width: 650px; margin: 16px auto; background-color: #FFFFFF; padding: 16px;">
        <h3>Hello world!</h3>
        <p>This demo app shows you how to add user authentication to your app using Authgear</p>
        <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        
        <p><a href="login.php">Login</a></p>
        <p><a href="logout.php">Logout</a></p>
    </div>
</body>
</html>
composer require league/oauth2-client
<?php
require 'vendor/autoload.php';

$appUrl = "PLACE_YOUR_PROJECT_URL_HERE";
$clientID = "PLACE_YOUR_CLIENT_ID_HERE";
$clientSecret = "PLACE_YOUR_CLIENT_SECRET_HERE";
$redirectUri = "PLACE_YOUR_REDIRECT_URI_HERE";

$provider = new \League\OAuth2\Client\Provider\GenericProvider([
    'clientId'                => $clientID,    // The client ID assigned to you by the provider (authgear).
    'clientSecret'            => $clientSecret,    // The client secret is assigned to you by the provider.
    'redirectUri'             => $redirectUri, // The authorized Redirect URI you specified in your authgear app.
    'urlAuthorize'            => $appUrl.'/oauth2/authorize',
    'urlAccessToken'          => $appUrl.'/oauth2/token',
    'urlResourceOwnerDetails' => $appUrl.'/oauth2/userInfo',
    'scopes' => 'openid offline_access'
]);
?>
<?php
include "config.php";

if (!isset($_GET['code'])) {
    // Fetch the authorization URL from the provider; this returns the
    // urlAuthorize option and generates and applies any necessary parameters
    // (e.g. state).
    $authorizationUrl = $provider->getAuthorizationUrl();

    // Redirect the user to the authorization URL.
    header('Location: ' . $authorizationUrl);
    exit;
}
?>
$appUrl = "REPLACE WITH YOUR AUTHGEAR PROJECT URL";
include "config.php";
session_start();

// if code is set, get access token
if (isset($_GET['code'])) {
    $code = $_GET['code'];

    try {
        $accessToken = $provider->getAccessToken('authorization_code', [
            'code' => $code
        ]);
        $_SESSION['accessToken'] = $accessToken;
        $_SESSION['refreshToken'] = $accessToken->getRefreshToken(); //store refresh token so that you can use it later
    } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
        // Failed to get the access token or user details.
        exit($e->getMessage());
    }
}
<div style="max-width: 650px; margin: 16px auto; background-color: #FFFFFF; padding: 16px;">
        <h3>Hello world!</h3>
        <p>This demo app shows you how to add user authentication to your app using Authgear</p>
        <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        <?php
        if (isset($_SESSION['accessToken'])) {

            //if access token exists in session, attempt to fetch user info
            $storedAccessToken = $_SESSION['accessToken'];
            $resourceOwner = $provider->getResourceOwner($storedAccessToken);
            $userInfo = $resourceOwner->toArray();

            echo "Welcome back " . $userInfo['email'];
            echo "<br/>";
            echo '<a href="">Logout</a>';
            
        } else { ?>
        <p><a href="login.php">Login</a></p>
        
        <?php
        } 
        ?>
    </div>
$resourceOwner = $provider->getResourceOwner($storedAccessToken);
if ($storedAccessToken->hasExpired()) {              
    $newAccesstoken = $provider->getAccessToken('refresh_token', [
        'refresh_token' => $_SESSION['refreshToken']
    ]);

    $_SESSION['accessToken'] = $newAccesstoken;
    $resourceOwner = $provider->getResourceOwner($newAccesstoken);
} else {
    $resourceOwner = $provider->getResourceOwner($storedAccessToken);
}
<?php 
include "config.php";
session_start();
if (isset($_SESSION['accessToken'])) {
    $options = [];
    $options['headers']['content-type'] = 'application/x-www-form-urlencoded';
    $options['body'] = http_build_query(['token'=>$_SESSION['refreshToken']]);
    $request = $provider->getRequest(
        'POST',
        $appUrl. '/oauth2/revoke',
        $options
    );
    $provider->getResponse($request);

    $_SESSION['accessToken'] = null;
    $_SESSION['refreshToken'] = null;
}
flask>=2.0.3
python-dotenv>=0.19.2
authlib>=1.0
requests>=2.27.1
import json
from os import environ as env
from urllib.parse import quote_plus, urlencode

from authlib.integrations.flask_client import OAuth
from dotenv import find_dotenv, load_dotenv
from flask import Flask, redirect, render_template, session, url_for
oauth = OAuth(app)

oauth.register(
    "authgear",
    client_id=env.get("AUTHGEAR_CLIENT_ID"),
    client_secret=env.get("AUTHGEAR_CLIENT_SECRET"),
    client_kwargs={
        "scope": "openid offline_access",
    },
    server_metadata_url=f'https://{env.get("AUTHGEAR_DOMAIN")}/.well-known/openid-configuration',
)
@app.route("/login")
def login():
    return oauth.authgear.authorize_redirect(
        redirect_uri=url_for("callback", _external=True)
    )
@app.route("/callback", methods=["GET", "POST"])
def callback():
    token = oauth.authgear.authorize_access_token()
    session["user"] = token
    return redirect("/")
@app.route("/logout")
def logout():
    session.clear()
    return redirect(
        "https://"
        + env.get("AUTHGEAR_DOMAIN")
        + "/oauth2/end_session"
    )
@app.route("/")
def home():
    return render_template(
        "home.html",
        session=session.get("user"),
        pretty=json.dumps(session.get("user"), indent=4),
    )
<html>
  <head>
    <meta charset="utf-8" />
    <title>Authgear Flak Login Example</title>
  </head>
  <body>
    <div data-gb-custom-block data-tag="if">
    <h1>Welcome {{session.userinfo.name}}!</h1>
    <p><a href="/logout" id="qsLogoutBtn">Logout</a></p>
    <div><pre>{{pretty}}</pre></div>
    <div data-gb-custom-block data-tag="else"></div>
    <h1 id="profileDropDown">Welcome Guest</h1>
    <p><a href="/login" id="qsLoginBtn">Login</a></p>
    </div>
  </body>
</html>
Backend Integration
Sign up
Composer
Portal
OAuth 2.0 Client
our example app on Github
documentation page
Flask
Authlib
GitHub repo
Sign up
Python
Pip
Dashboard
Authgear Portal UI
http://localhost:3000
http://localhost:3000
Magic links
social logins
WhatsApp OTP
add more users
http://localhost:3000/callback

Authenticate

Implement Authgear to control access to your applications

Authgear simplifies the use of open industry standards like OAuth 2.0, and OIDC. Users can log into your applications with a variety of user login options. This set of how-to guides provides you with detailed instructions, code snippets, and configuration examples for each type of login method.

Backend Integration

Decide how your backend application server authenticate the incoming HTTP requests.

For Mobile App or Single Page Web App or Website, each request from the client to your application server should contain an access token or a cookie. Your backend server should validate them for each HTTP request.

There are different approaches to verify the requests based on whether you validate JWT (JSON Web Tokens) in your server, or forward authentication to Authgear Resolver Endpoint.

Validate JWT in your server

JWT Token in Authorization Header

JWT Token in Cookies

Forward Authentication to Authgear Resolver Endpoint

Forward Authentication is a process where an intermediate reverse proxy or API Gateway is responsible for authenticating a request before it reaches the intended application or service. This can add an extra layer of security and centralize the authentication logic. An intermediate service forwards each incoming HTTP request to the Authgear Resolver Endpoint to verify the access token or cookie in the HTTP header.

Forward Authorization Header

Forward Cookie in HTTP header

Comparison

Validate JSON Web Token (JWT) in your application server

Forward Authentication to Authgear Resolver Endpoint

Reliability

Medium JWT only updates when expire. That means before the token expiry, your application may see the user is valid even they has been disabled

High Update near real-time, based on your reserve proxy cache setting

Integration difficulties

Easy You only need to add code in your application to validate and decode JWT

Medium Need to setup extra reverse proxy to resolve authentication information

Setup guides

Validate JSON Web Token (JWT) in your application server

Forward authentication with Authgear Resolver Endpoint

Express

Authentication for Express.JS apps with Authgear and OAuth2

Authgear makes it easy to add user authentication to a regular web app that is not powered by any framework. You can do this by implementing OAuth2 in your app with Authgear as the provider.

In this post, you'll learn how to add user authentication to an Express.js application using Authgear.

What You Will Learn

  • How to create an Authgear Application

  • How to sign in with Authgear from an Express app using an authorization code.

  • How to request user info from Authgear

Pre-requisites

You'll need the following to follow along with this tutorial:

  • Node.js Installed

  • A free Authgear account. Sign up for one here.

How to Add User Authentication to Express.js App using Authgear

For this tutorial, we'll be building a simple Express app that has the following features:

  • A landing page with a login link that takes users to the login route.

  • A /login route that redirects users to the Authgear OAuth authorization page.

  • Logic that exchanges the authorization code from Authgear for an access token.

  • A page that uses that access token to fetch user info from Authgear.

Step 1: Configure Authgear Application

In order to use Authgear as an OAuth identity provider in your application, you need to configure an Authgear project. This project gives you all the credentials that you'll be using to send requests from your application.

Now let's create a new application.

Log in to the Authgear portal, and select your project. From the project dashboard, navigate to the Applications section and enter your application details as shown below:

Once you're done, click on Save to reveal the OAuth configuration. The application configuration page is where you can find your OAuth credentials like client ID, client secret, and a list of supported endpoints. Note down the configuration details as you'll use them later in your Express app.

Step 2: Set Redirect URI

You need to provide one or more URLs within your app for Authgear to redirect to after user authorization.

To add a URL, scroll to the URIs and click on the Add button. Enter the full URL for the page you wish to redirect users to after login. For our example app for this post, we'll set this URL to http://localhost:3000.

Step 3: Create Express App

It is now time to set up the Express app that will be interacting with Authgear. To do that, create a new folder with the name "express-auth-example", this will be your Express project folder. Next, run the following command from the project folder :

npm install express

We'll be using the Axios library to make HTTP requests in the example app. Install Axios to your project by running this command:

npm install axios

Once Express is installed, create a new app.js file in the root of your project folder and add the following code to the file:

const express = require('express');
const axios = require('axios');

const config = {
  client: {
    id: "",
    secret: "",
    redirect_url: "http://localhost:3000"
  },
  auth: {
    tokenHost: 'https://your-project.authgear.cloud',
    tokenPath: '/oauth2/token',
    authorizePath: '/oauth2/authorize',
  },
};

app.get("/", async (req, res) => {
  res.send(`
      <div style="max-width: 650px; margin: 16px auto; background-color: #EDEDED; padding: 16px;">
        <p>Hi there!</p>
        <p>This demo app shows you how to add user authentication to your Express app using Authgear</p>
          <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        <a href="/login">Login</a>
      </div>
    `);
});

app.listen(3000, () => {
  console.log("server started!");
});

Note: Paste the correct values of client id, client secret, and redirect URL for your Authgear app inside the client object in the config variable. Also, set tokenHost to the hostname part of your Authgear app endpoint URL. That is the part before the first "/". For example, tokenHost for https://example.authgear.cloud/oauth2/token will be https://demo-1-ea.authgear.cloud.

Run your app.js file using the node app.js command. You should get a page like this on a web browser when you visit localhost:3000:

Step 4: Add Login Endpoint

Here we'll be implementing a local login endpoint in our Express app. This endpoint will handle requests from the above login link.

Add a new route to your express app using the following code:

app.get("/login", (req, res) => {
  res.redirect(`${config.auth.tokenHost}${config.auth.authorizePath}/?client_id=${config.client.id}&redirect_uri=${config.client.redirect_url}&response_type=code&scope=openid`);
});

Now if you save your code and restart your app, clicking on the login link should redirect to the Authgear authorization page.

Step 5: Exchange Authorization Code For Access Token

After the user logs in and grants authorization to your app on Authgear, they are redirected back to the redirect URL you specified earlier. In addition to this redirect, an authorization code is sent via a code URL query parameter.

In this step, we will be exchanging the authorization code for an access code that users can later use to access protected resources.

Update the code for the app.get("/") route to the following:

app.get("/", async (req, res) => {

  if (req.query.code != null) {
    const data = {
      client_id: config.client.id,
      client_secret: config.client.secret,
      code: req.query.code,
      grant_type: 'authorization_code',
      response_type: 'code',
      redirect_uri: config.client.redirect_url,
      scope: "openid",
    };

    try {
      const getToken = await axios.post(`${config.auth.tokenHost}${config.auth.tokenPath}`, data, {
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
      });

      const accessToken = getToken.data.access_token;
      console.log(accessToken);

      res.send("Welcome");

    } catch (error) {
      console.log(error);
      res.send("An error occurred! Could not complete login. Error data: " + error);
    }
  }

  else {
    res.send(`
      <div style="max-width: 650px; margin: 16px auto; background-color: #EDEDED; padding: 16px;">
        <p>Hi there!</p>
        <p>This demo app shows you how to add user authentication to your Express app using Authgear</p>
          <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        <a href="/login">Login</a>
      </div>
    `);
  }
});

The above code sends an HTTP POST request to the token endpoint. The authorization code we got from the previous step is sent along with other client credentials in the HTTP request body. The header should contain "Content-Type": "application/x-www-form-urlencoded"

A valid access token is returned in the response to the Axios response in response.data.access_token.

We can now use this access token to make authenticated requests to protected resources in our app or from Authgear endpoint. In the next step, we'll attempt to get the current user's info from Authgear using the access token.

Step 6: Get User Info

Authgear provides an endpoint where your application can request user info. This endpoint will return the user's details on Authgear like their email address, gender, full name, and more.

To get user info in our example app, in app.js, replace this line :

res.send("Welcome");

with the following code:

//Now use access token to get user info.
const getUserInfo = await axios.get(`${config.auth.tokenHost}/oauth2/userinfo`, { headers: { "Authorization": "Bearer " + accessToken } });
const userInfo = getUserInfo.data;
res.send(`
   <div style="max-width: 650px; margin: 16px auto; background-color: #EDEDED; padding: 16px;">
           <p>Welcome ${userInfo.email}</p>
           <p>This demo app shows you how to add user authentication to your Express app using Authgear</p>
           <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
       
   </div>
`);

This code sends another HTTP request, but this time to the user info endpoint and the request type is GET. The access token is sent as a Bearer authorization header.

At this point, save all changes and restart the application. Try logging in all over again, at the end you should be greeted with "Welcome [your email address]".

Conclusion

And there you have it, you've successfully added user authentication to your Express app using Authgear as the OAuth provider.

You can add so much more to your app with the new Authgear authentication, like protecting your own app endpoint with the access code. You can also store the access token securely to persist the user session using express-session and cookies.

Laravel

Authentication for Laravel websites with Authgear and OAuth2

In this guide, you'll learn how to add user authentication to a Laravel app using Authgear as an OIDC provider.

Authgear supports multiple ways to allow users to log in to apps such as passwordless sign-in, phone OTP, and 2FA. In this post, we'll show you how to enable all these options in your Laravel app without worrying about the underlying logic.

What You Will Learn

  • How to create an Authgear Application.

  • How to request OAuth 2.0 authorization code from Authgear.

  • How to get user info from Authgear using OAuth 2.0 access code.

  • Link user info from Authgear with Laravel's default Breeze authentication.

Pre-requisites

To follow along with the example, you should have the following in place:

  • A Laravel project.

What We Will Build

The example app we'll build in this post uses the default Laravel Breeze authentication kit. This kit provides the starter code for email and password user authentication systems.

We will be using Authgear to handle and process authentication data instead of the default Breeze database. By doing so, we get all the benefits of Authgear including more security and flexibility.

How to Add User Authentication to Laravel with Authgear as an OAuth Provider

In this section, we'll walk through the complete steps for building the example app.

Step 1: Configure Authgear Application

Before we can use Authgear as an OAuth identity provider, we need to set up an application on the Authgear portal.

To do that, log in to Authgear then select a project. Next, navigate to the Applications section for your project. Create a new application or configure an existing one with OIDC Client Application as Application Type as shown below:

Once you're done, click on Save to go to the application configuration page. This page reveals the application credentials and OAuth 2.0 endpoints.

Note down details like the Client ID, Client Secret, and the endpoints as you'll use them later in your Laravel project.

Step 2: Add a Redirect URI

While you're still on the application configuration page, scroll down to the URL section then click on Add URI. Enter localhost:8000/oauth/callback in the text field if you will be running your Laravel app on your local machine. Once you're done, click Save.

The redirect URI we provided above should be a valid page on our Laravel app as Authgear will redirect users to the page after authorization.

Step 3: Create a Laravel Project

Now create a new Laravel project on your computer by running the following command:

composer create-project laravel/laravel authgear-laravel-example

Once your project is created, open the project folder in your preferred code editor and replace the content of resources/views/welcome.blade.php with the following code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP Demo - Home</title>
</head>
<body style="background-color: #DEDEDE">
    <div style="max-width: 650px; margin: 16px auto; background-color: #FFFFFF; padding: 16px;">
        <h3>Hello world!</h3>
        <p>This demo app shows you how to add user authentication to your Laravel app using Authgear</p>
        <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        
        <p><a href="/login">Login</a></p>
    </div>
</body>
</html>

Alternatively, you can create a new index.blade.php file in the resources folder and add the above code inside it. Then, update the web.php route file to render the new file instead of welcome.blade.php.

Next, run the php artisan serve command in the terminal to test your application. At this point, your application should look like the following screenshot when you access localhost:8000 on a browser:

Step 4: Install Laravel Breeze

Breeze is the official user authentication starter kit for Laravel. What that means is that Breeze helps you set up the database, routes, controller, and user interface for a user registration and user login system.

To install Breeze on your Laravel project, run the following command:

composer require laravel/breeze --dev

After that, run the following command to enable Breeze to set up all the resources for the user authentication system in your project:

php artisan breeze:install

During the setup, select blade as the stack and leave the other options as default.

Once the setup is complete, navigate around your project file structure and you should notice some new folders and files related to authentication were added. Some of these new folders/files include an Auth sub-folder in the controllers folder, another auth sub-folder inside the views folder, and some database migration files.

Before we continue, let's add an extra oauth_uid field to the users table migration file. This field will store a user's unique ID from Authgear after successful login.

Open the create_users_table... file that is inside the database/migrations/ folder (this file will have a date value at the end of its name) and add the following code to a new line inside the Schema::create() method:

$table->string('oauth_uid')->nullable();

Add the MySQL database DB_DATABASE, DB_USERNAME, and DB_PASSWORD for the database you wish to use with your Laravel project in your Laravel project's .env file.

Finally, create the users and other tables by running the following command:

php artisan migrate

Step 5: Send OAuth User Authorization Request

In this step, we'll create a new route that will handle the task of redirecting users from our app to Authgear's OAuth authorization page where they can grant our app authorization to their data on Authgear. If you've used other OAuth 2.0 providers before, for example, signing in to a website using Google OAuth, you may already be familiar with an authorization page.

First, create a new controller that will handle all OAuth operations in our Laravel app by running the following command:

php artisan make:controller OAuthController

Before we start implementing the logic for our new controller, we need to install a PHP OAuth 2.0 client package. This package will simplify the process of interacting with Authgear's OAuth endpoints. Run the following commands to install the package:

composer require league/oauth2-client

Now, back to implementing the controller; open the new OAuthController file (from the app/Http/Controllers folder) and add the following code to it:

use \League\OAuth2\Client\Provider\GenericProvider;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\User;

class OAuthController extends Controller {

    public $provider;

    public function __construct ()
    {
        $appUrl = env("AUTHGEAR_PROJECT_URL", "");
        $this->provider = new GenericProvider([
            'clientId'                => env("AUTHGEAR_APP_CLIENT_ID", ""),
            'clientSecret'            => env("AUTHGEAR_APP_CLIENT_SECRET", ""),
            'redirectUri'             => env("AUTHGEAR_APP_REDIRECT_URI", ""),
            'urlAuthorize'            => $appUrl.'/oauth2/authorize',
            'urlAccessToken'          => $appUrl.'/oauth2/token',
            'urlResourceOwnerDetails' => $appUrl.'/oauth2/userInfo',
            'scopes' => 'openid offline_access'
        ]);
    }

    public function startAuthorization() {
        $authorizationUrl = $this->provider->getAuthorizationUrl();
        return redirect($authorizationUrl);
    }

	public function handleRedirect() {

	}
}

Next, add your Authgear Application's Client ID, Client Secret, and the redirect URI you specified earlier to your Laravel project's .env file using the following keys:

AUTHGEAR_PROJECT_URL=""
AUTHGEAR_APP_CLIENT_ID=""
AUTHGEAR_APP_CLIENT_SECRET=""
AUTHGEAR_APP_REDIRECT_URI="http://localhost:8000/oauth/callback"

Note: Your Authgear project URL is the hostname of any of your endpoint URLs. For example, the project URL for a project with an authorization endpoint: https://laravel-app.authgear.cloud/oauth2/authorize will be https://laravel-app.authgear.cloud.

Now let's create a route in our Laravel project that will call the startAuthorization() method.

Open the routes/web.php file and add new routes using the following code:

Route::get('/login', [OAuthController::class, 'startAuthorization']);

Route::get('/oauth/callback', [OAuthController::class, 'handleRedirect']);

We've included a second route for the redirect URI (callback), we'll implement this route in the next step.

Before we continue, let's clean up some of the additional routes added by the Breeze package that we won't be needing for this example. Open the routes/auth.php file and delete the following lines:

Route::get('login', [AuthenticatedSessionController::class, 'create'])
                ->name('login');
                
Route::post('login', [AuthenticatedSessionController::class, 'store']);

At this point accessing the /login route should redirect to the Authgear authorization page.

Step 6: Implement Redirect URI Page

Update the empty handleRedirect() method in OAuthController to the following:

public function handleRedirect() {

        // if code is set, get access token
        $accessToken = null;
        if (isset($_GET['code'])) {
            $code = $_GET['code'];

            try {
                $accessToken = $this->provider->getAccessToken('authorization_code', [
                    'code' => $code
                ]);

            } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {

                // Failed to get the access token or user details.
                exit($e->getMessage());

            }
        }
}

The above code gets the authorization code sent in the redirect URL from Authgear after user authorization and exchanges it for an access token. With this access token, our application can access protected resources like the user info endpoint.

Step 7: Link User Info to Laravel User Authentication

In this step, we'll use the access token we got from the last step to get the current user's info from Authgear.

First, add the following code at the end of the handleRedirect() method:

//Use access token to get user info
if (isset($accessToken)) {
    $resourceOwner = $this->provider->getResourceOwner($accessToken);
    $userInfo = $resourceOwner->toArray();

}

The getResourceOwner() method will call Authgear's UserInfo endpoint.

If you dump the userInfo variable (dd($userInfo)), you should get an output similar to this:

[ 
  "custom_attributes" => []
  "email" => "users-email@gmail.com"
  "email_verified" => true
  "https://authgear.com/claims/user/can_reauthenticate" => true
  "https://authgear.com/claims/user/is_anonymous" => false
  "https://authgear.com/claims/user/is_verified" => true
  "sub" => "e1234323-f123-4b99-91d8-c2ca55a6a3dc"
  "updated_at" => 1683898685
  "x_web3" => []
]

The above array contains the user's info from Authgear. We'll proceed to use this information to link the Authgear user to a default (Breeze) Laravel authentication account. As a result, our app can start a regular Laravel authenticated user session and allow access to protected routes.

To implement the above feature, find the following line in OAuthController.php:

$userInfo = $resourceOwner->toArray();

Add the following code after the above line:

if (empty($userInfo['email'])) {
    return redirect('/')->withErrors(['msg' => 'Only profile with email is supported!']);
}
//check if user already registered
$oldUser = User::query()->whereEmail($userInfo['email'])->first();
if (!empty($oldUser)) {

    //if old user has the same Authgear sub (uuid), skip register and log them in.
    if ($userInfo['sub'] == $oldUser->oauth_uid) {
        Auth::guard('web')->login($oldUser);
        session(['accessToken' => $accessToken]);
        session(['refreshToken' => $accessToken->getRefreshToken()]);
    } else {
        //if sub is different,
        //ask user to login to existing account and link the existing account to link new authgear profile
        return redirect('/')->withErrors(['msg' => 'Email already registered please log in to link your account.']);
    }
} else {
    $user = User::create([
        'name' => $userInfo['email'],
        'email' => $userInfo['email'],
        'oauth_uid' => $userInfo['sub'],
        'password' => Hash::make($userInfo['sub'] . "-" . $userInfo['email'])
    ]);

    Auth::guard('web')->login($user);
    session(['accessToken' => $accessToken]);
    session(['refreshToken' => $accessToken->getRefreshToken()]);
}

// Redirect user to a protected route
return redirect('/dashboard');

Step 8: Using Refresh Token

OAuth 2.0 access tokens expire after some time. The refresh token on the other hand live longer. As a result, you can use the refresh token to request a new access token. In this step, we'll do exactly that in our Laravel application.

First, app/Http/Controllers/ProfileController.php and update the content of the edit() method to the following:

public function edit(Request $request): View
{
    $appUrl = env("AUTHGEAR_PROJECT_URL", "");
    $provider = new GenericProvider([
        'clientId'                => env("AUTHGEAR_APP_CLIENT_ID", ""),
        'clientSecret'            => env("AUTHGEAR_APP_CLIENT_SECRET", ""),
        'redirectUri'             => env("AUTHGEAR_APP_REDIRECT_URI", ""),
        'urlAuthorize'            => $appUrl . '/oauth2/authorize',
        'urlAccessToken'          => $appUrl . '/oauth2/token',
        'urlResourceOwnerDetails' => $appUrl . '/oauth2/userInfo',
        'scopes' => 'openid offline_access'
    ]);

    $accessToken = session('accessToken');

    if ($accessToken->hasExpired()) {
        $refreshToken = session('refreshToken');
        $accessToken = $provider->getAccessToken('refresh_token', [
            'refresh_token' => $refreshToken
        ]);
        session(['accessToken' => $accessToken]);
    }
    $resourceOwner = $provider->getResourceOwner($accessToken);
    $userInfo = $resourceOwner->toArray();


    return view('profile.edit', [
        'user' => $request->user(), 'authgearUserInfo' => $userInfo,
    ]);
}

The above code checks if the current access token is expired using the hasExpired() method. If the condition is true, we call the getAccessToken() method with the refresh token to get a new access token.

The value of the current access token is updated to the new access token.

Next, this edit() method also displays the current user's profile details from your Authgear project on the UI. To implement this, add the following code to resources/views/profile/edit.blade.php, just below the line with "<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">":

<div class="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
    <div class="max-w-xl">
        <h2>Authgear user data</h2>
        <p>Email: {{ $authgearUserInfo['email'] }}</p>
        <p>UUID: {{ $authgearUserInfo['sub'] }}</p>
    </div>
</div>

At this point, if we run our app and click on the login link on the landing page, we should be redirected to the Authgear authorization page. After granting authorization, we are directed to the callback route of our Laravel app. If authentication is successful we should be redirected to the default Breeze-protected dashboard page that looks like this:

Step 9: Logout

To log a user out, we'll delete all existing PHP session data and then call the Authgear token revoke endpoint.

First, add a new logout function to the OAuthController.php file using the following code:

public function logout(Request $request)
{
    Auth::guard('web')->logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    if (session('accessToken') != null) {
        $options = [];
        $options['headers']['content-type'] = 'application/x-www-form-urlencoded';
        $options['body'] = http_build_query(['token'=>session('refreshToken')]);
        $request = $this->provider->getRequest(
            'POST',
            env("AUTHGEAR_PROJECT_URL", "") . '/oauth2/revoke',
            $options
        );
        $this->provider->getResponse($request);
    
        session(['accessToken' => null]);
        session(['refreshToken' => null]);
    }

    return redirect('/');
}

Then, open routes/web.php and update the logout route to the following:

Route::post('logout', [OAuthController::class, 'logout'])
                ->name('logout');

What's Next

You should try enabling the different login methods on Authgear from the Portal to enjoy features like 2FA, passwordless login, and more without updating anything on the code for your app.

Cookie-based (Website or Single-page app)

Authenticate incoming request by cookie in the HTTP header.

By using Authgear, you can add a login to your website easily. Authgear supports various authentication methods, that you can easily turn on and configure in the portal.

Prerequisites

To authenticate with cookies, you will need to set up a custom domain for Authgear, so that your website and Authgear are under the same root domains. e.g. Your website is yourdomain.com, and Authgear with a custom domain auth.yourdomain.com.

In this setting, if you have multiple applications under yourdomain.com, all applications would share the same session cookies automatically.

Overview

How it works

Your app server will receive a request with the cookie

Verify request in your app server

To verify the requests in your app server, you must Forward authentication to Authgear Resolver Endpoint.

Request example

Get Started

The following tutorials show you how to add user login to your website using Authgear.

1. Frontend Integration

2. Backend Integration

Choose your authentication approach

Decide how should the application requests be identified, either by access tokens or by cookies.

Authgear provides token-based or cookie-based authentication. You will need to decide which approach you are going to use before starting the setup.

Token-based authentication

This approach is suitable for mobile apps or single-page web applications.

In Token-based authentication, Authgear returns the access token and refresh token to the client app after authentication.

The client SDK will automatically renew the access token with the refresh token for you, so you don't have to worry about it.

Request example:

Cookie-based authentication

This approach is suitable for all types of websites, including server-side rendered applications.

In Cookie-based authentication, Authgear returns Set-Cookie headers and sets cookies to the browser. The cookies are HTTP only and share under the same root domains. So you will need to setup the custom domain for Authgear, such as identity.yourdomain.com.

Request example:

Forward Authentication to Authgear Resolver Endpoint

Authenticate the incoming HTTP requests by forwarding Authentication to Authgear Resolver Endpoint

In this section, we will explain how to set up a reverse proxy in NGINX to protect your app server from unauthorized access with the Authgear resolver. You can forward the requests without the request body to the resolver endpoint. Authgear will look at the Authorization and Cookie in the HTTP header, verify the token, and respond to HTTP 200 with X-Authgear- headers for session validity, the user id...etc.

You can also use the forward authentication features of the other popular reverse proxy. e.g.

Authgear Resolver Endpoint

Authgear provides an endpoint for forward authentication. Subrequests should be made to the following endpoint for authentication.

https://<your_app_endpoint>/_resolver/resolve

How Forward Authentication Works

  1. After the user is logged in, send an application request to your server from the client app with access token/cookies.

  2. Set up a reverse proxy in your infrastructure to authenticate HTTP requests. The reverse proxy will forward the incoming HTTP requests without the request body to the Authgear Resolver Endpoint.

  3. Authgear resolver parses the access token and returns HTTP headers including the user login state. The headers are starting with x-authgear-.

  4. You have to instruct your reverse proxy to include those extra headers, before forwarding the request to your backend server.

  5. Your backend server looks at the headers and responds to the client app accordingly. e.g. Returns the user's content or HTTP 401 if the user is not logged in.

There are so many reverse proxies available in the wild. So here we are going to illustrate the idea of using Nginx as the reverse proxy.

Using Nginx as the reverse proxy

We will use the module auth_request in NGINX. The module is not built by default, it should be enabled with the --with-http_auth_request_moduleconfiguration parameter.

Run this command and verify that the output includes --with-http_auth_request_module:

The trick here is to declare an internal location and use auth_request to initiate a subrequest to the resolved endpoint.

Example configuration

Optimizing the performance

If the reverse proxy, Authgear, and your backend server are in different regions, authenticating every request could result in a huge downgrade in the performance.

You may consider enabling caching.

Reference on the headers

Validate JWT in your application server

Authenticate the incoming HTTP requests by validating JWT in your application server

In this section, we will go through how to decode the JWT token to obtain the currently logged-in user.

Before we start, make sure the option Issue JWT as access token is enabled in your Application settings in the Portal.

With the Issue JWT as access token option turned on in your application, Authgear will issue JWT as access tokens. The incoming HTTP requests should include the access token in their Authorization headers. Without setting the reverse proxy, your backend server can use your Authgear JWKS to verify the request and decode user information from the JWT access token.

Find the JSON Web Key Sets (JWKS) endpoint

This Discovery endpoint serves as a JSON document containing the OpenID Connect configuration of your app. It includes the authorization endpoint, the token endpoint, and the JWKS endpoint.

https://<YOUR_AUTHGEAR_ENDPOINT>/.well-known/openid-configuration

The JSON Web Key Sets (JWKS) endpoint can be found in jwk_url in the configuration.

OpenID Connect Configuration JSON

Decode user from an access token

Follow this step-by-step example to verify and decode the JWT token.

Step 1: Install packages

Step 2: Find the JSON Web Key Sets (JWKS) endpoint

Define a function to find the JWKS endpoint from the OpenID Connect configuration. Use your Authgear endpoint as the base_address

Step 3: Get the JWT token from the Authorization header

Define a function to extract the access token from the Authorization header in the incoming request. It should look like Authorization: Bearer <access_token>.

Step 4: Verify and decode the JWT token

Here we show an example of using the Flask web framework to guard a path. You may need to adjust some of the codes to suit your technologies.

Step 1: Install dependencies

Step 2: Find the JWKS Endpoint

Use the following method to get the JWKS URI (you'll need to URI to extract the public signing key from a JWT).

Step 3: Extract JWT from Request Header

Use the following code to extract only the token part from a Bearer [token] authorization header in your Express app:

Step 4: Decode Access Token

Next, decode the access token so that you can extract the JWT kid from the result. You'll need this `kid to get the public signing key. Use the following code to decode the JWT:

Step 5: Get JWT Signing Keys and Verify the JWT

Use the following code to extract the JWT public keys then verify the JWT using the keys:

Here's what your Express app should look like after putting the code in all the steps together:

Use your Authgear endpoint as base_address

Step 1: Install Packages

First, install the dependencies required by running these com

Step 2: Find the JWKS Endpoint

Create a function that finds the JWKS endpoint from your Authgear application endpoint using the following code:

Step 3: Get Signing Key

Add the following code to your application to get the JWT signing key:

Step 4: Extract the JWT From the Request Header

To extract the access token from the HTTP request use the following code:

Step 5: Validate and Decode JWT

Finally, decode the JWT signing key.

Check the validity of JWT

Decode user from cookies

Validating JWT in your application server is currently only available for Token-based authentication.

Authgear uses for secure data transmission, authentication, and authorization. Tokens should be parsed and validated in regular web, native, and single-page applications to make sure the token isn’t compromised and the signature is authentic.

Read more on guide.

This approach is only available for and involves passing the JWT token within the HTTP Authorization header. This approach is widely used in OAuth 2.0 and OIDC implementations, providing a standardized way to authenticate users.

JWT tokens can be stored in HTTP cookies and sent with each request. It is suitable for . Storing JWTs in cookies as a way to persist the user's session across requests. The server then uses JWKS to validate the token. This approach is useful in scenarios where you want to maintain user sessions across different services in a more traditional web application setup.

For Cookie-based authentication, JWT in cookies is not supported yet. .

Read more on guide.

Before processing the request, your server or a reverse proxy forwards the request to an . This endpoint resolves and verifies the authentication information (such as an Access Token) from the request Authorization Header.

In this pattern, Access Token (JWT) is stored in a cookie, and your server or a reverse proxy may contact the to obtain more information or validate certain aspects of the request.

Here's a link to the complete code for .

A free Authgear account. if you don't have an account yet.

Find the complete code for the OAuthController .

Find the complete code for the example app in our .

Your client app should call your backend with the access token in the Authorization header, and you can verify the access token by integrating Authgear with your backend. The HTTP requests can be authenticated by or .

In this setting, if you have multiple applications under yourdomain.com, all applications would share the same session cookie automatically. After that, you can verify the cookies by integrating Authgear with your backend. The HTTP requests must be authenticated by .

If you use a popular reverse proxy on your deployment, such as , , or API Gateways such as , you can configure it with a few simple lines of forward auth config. Your backend should read the returned headers to determine the identity of the user of the HTTP request.

See docs for auth_request in NGINX for more details.

See the list of x-authgear- headers in the specs:

Here is .

The auth_time claim in an OIDC ID token represents the time when the user authentication occurred. Extract the auth_time claim from the token, which should represent the time of the original authentication in seconds. If the difference between the current time and auth_time exceeds your threshold (for example, 5 minutes), initiate the process.

See an example of how to verify the signature of the ID token, and then validate the claims auth_time inside .

For Cookie-based authentication, JWT in cookies is not supported yet. .

JSON Web Token (JWT)
Validate JWT in your application server
Token-based authentication
Cookie-based authentication
You can track the issue here
Forward Authentication to Authgear Resolver Endpoint
Validate JWT in your application server
Forward Authentication to Authgear Resolver Endpoint
our example code on Github
Sign up
here
Laravel Example Github repo
> GET /api_path HTTP/1.1
> Host: yourdomain.com
> cookie: session=<AUTHGEAR_SESSION_ID>

Token-based

Cookie-based

Suitable for

mobile apps or single-page web applications

Websites in the same root domain (e.g. Server-side rendered applications)

Transport of session

Access Token in Authorization header

Session ID in Cookies

> GET /api_path HTTP/1.1
> Host: yourdomain.com
> Authorization: Bearer <AUTHGEAR_ACCESS_TOKEN>
> GET /api_path HTTP/1.1
> Host: yourdomain.com
> cookie: session=<AUTHGEAR_SESSION_ID>
$ nginx -V 2>&1 | grep -- 'http_auth_request_module'
server {
  # Use variable in proxy_pass with resolver to respect DNS TTL.
  # Note that /etc/hosts and /etc/resolv.conf are NOT consulted if resolver is used.
  # See https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
  resolver 8.8.8.8;
  
  # Location that requires request authentication
  location / {
    set $backend http://www.mycompany.com;
    proxy_pass $backend;
    proxy_set_header Host $host;
    # Specify the auth_request directive to initiate subrequests to the to the internal location.
    # This corresponds to the Step 2.
    auth_request /_auth;

    # Copy the `x-authgear-*` headers from the response of the subrequest to Nginx variables.
    # This corresponds to the Step 3.
    auth_request_set $x_authgear_session_valid $upstream_http_x_authgear_session_valid;
    auth_request_set $x_authgear_user_id $upstream_http_x_authgear_user_id;
    auth_request_set $x_authgear_user_anonymous $upstream_http_x_authgear_user_anonymous;
    auth_request_set $x_authgear_user_verified $upstream_http_x_authgear_user_verified;
    auth_request_set $x_authgear_session_acr $upstream_http_x_authgear_session_acr;
    auth_request_set $x_authgear_session_amr $upstream_http_x_authgear_session_amr;
    auth_request_set $x_authgear_session_authenticated_at $upstream_http_x_authgear_session_authenticated_at;
    auth_request_set $x_authgear_user_can_reauthenticate $upstream_http_x_authgear_user_can_reauthenticate;

    # Include the headers in the request that will be sent to your backend server.
    # This corresponds to the Step 4.
    proxy_set_header x-authgear-session-valid $x_authgear_session_valid;
    proxy_set_header x-authgear-user-id $x_authgear_user_id;
    proxy_set_header x-authgear-user-anonymous $x_authgear_user_anonymous;
    proxy_set_header x-authgear-user-verified $x_authgear_user_verified;
    proxy_set_header x-authgear-session-acr $x_authgear_session_acr;
    proxy_set_header x-authgear-session-amr $x_authgear_session_amr;
    proxy_set_header x-authgear-session-authenticated-at $x_authgear_session_authenticated_at;
    proxy_set_header x-authgear-user-can-reauthenticate $x_authgear_user_can_reauthenticate;

    # Your backend must inspect the request headers to determine whether the request is authenticated or not.
    # This corresponds to the Step 5.
  }

  location = /_auth {
    # Set this location for internal use only
    internal;
    # Replace <YOUR_AUTHGEAR_ENDPOINT> with your authgear endpoint.
    # For example, https://example.authgear.cloud
    set $resolver <YOUR_AUTHGEAR_ENDPOINT>/_resolver/resolve;
    proxy_pass $resolver;
    # Set the host so that authgear knows which app is calling the resolver endpoint
    # Replace <YOUR_AUTHGEAR_ENDPOINT_HOST> with the host of your authgear endpoint.
    # For example, example.authgear.cloud
    proxy_set_header Host <YOUR_AUTHGEAR_ENDPOINT_HOST>;
    # The body is supposed to be consumed by your backend server.
    # Pass only the headers to the resolver
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
  }
}
http {
  # ...
  proxy_cache_path /tmp/cache keys_zone=auth_cache:10m;

  # The server block.
  server {
    # ...
    location = /_auth {
      # ...
      proxy_cache auth_cache;
      proxy_cache_key "$cookie_session|$http_authorization";
      proxy_cache_valid 200 10m;  # Adjust cache duration as desired.
    }
  }
}
Authgear Resolver Endpoint
Authgear Resolver Endpoint
{
    "jwks_uri": "..."
    ...
}
pip install cryptography
pip install PyJWT
import json
from contextlib import closing
from urllib.request import urlopen

base_address = "https://<your_app_endpoint>"

def fetch_jwks_uri(base_address):
    doc_url = base_address + "/.well-known/openid-configuration"
    with closing(urlopen(doc_url)) as f:
        doc = json.load(f)
    jwks_uri = doc["jwks_uri"]
    if not jwks_uri:
        raise Exception('Failed to fetch jwks uri.')
    return jwks_uri
def parse_header(authz_header):
    parts = authz_header.split(" ")
    if len(parts) != 2:
        return

    scheme = parts[0]
    if scheme.lower() != "bearer":
        return

    return parts[1]
from flask import request
import jwt
from jwt import PyJWKClient

@app.route("/hello")
def hello():
    authz_header = request.headers.get("Authorization")
    if not authz_header:
        return {
            "message": "authz header not found"
        }

    # get jwt token from Authorization header
    token = parse_header(authz_header)
    if token:
        try:
            # fetch jwks_uri from the Authgear Discovery Endpoint
            jwks_uri = fetch_jwks_uri(base_address)
            # Reuse PyJWKClient for better performance
            jwks_client = PyJWKClient(jwks_uri)
            signing_key = jwks_client.get_signing_key_from_jwt(token)
            user_data = jwt.decode(
                token,
                signing_key.key,
                algorithms=["RS256"],
                audience=base_address,
                options={"verify_exp": True},
            )
            return {
                "message": "Hello!",
                "user_data": user_data
            }
        except:
            return {
                "message": "JWT decode failed"
            }
    else:
        return {
            "message": "no token"
        }
npm install --save axios jwks-rsa jsonwebtoken
const appUrl = ""; //place your authgear app endpoint here
const getJwksUri = async (appUrl) => {
    const config_endpoint = appUrl + "/.well-known/openid-configuration";
    const data = await axios.get(config_endpoint);
    return data.data.jwks_uri;
}
const express = require("express");
const axios = require("axios");
const node_jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

const app = express();
const port = 3002;
app.get('/', async (req, res) => {

    const requestHeader = req.headers;
    if (requestHeader.authorization == undefined) {
        res.send("Invalid header");
        return;
    }
    const authorizationHeader = requestHeader.authorization.split(" ");
    const access_token = authorizationHeader[1];

}
const decoded_access_token = node_jwt.decode(access_token, {complete: true});
const jwks_uri = await getJwksUri(appUrl);
    const client = jwksClient({
        strictSsl: true,
        jwksUri: jwks_uri
    });
    const signing_key = await client.getSigningKey(decoded_access_token.header.kid);

    try {
        const verify = node_jwt.verify(access_token, signing_key.publicKey, { algorithms: ['RS256'] });
        res.send(JSON.stringify(verify))
    }
    catch(error) {
        res.send(error);  
    }
    
const express = require("express");
const axios = require("axios");
const node_jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

const app = express();
const port = 3002;

const appUrl = "https://demo-1-ea.authgear.cloud";
const getJwksUri = async (appUrl) => {
    const config_endpoint = appUrl + "/.well-known/openid-configuration";
    const data = await axios.get(config_endpoint);
    return data.data.jwks_uri;
}

app.get('/', async (req, res) => {

    const requestHeader = req.headers;
    if (requestHeader.authorization == undefined) {
        res.send("Invalid header");
        return;
    }
    const authorizationHeader = requestHeader.authorization.split(" ");
    const access_token = authorizationHeader[1];
    const decoded_access_token = node_jwt.decode(access_token, {complete: true});
    const jwks_uri = await getJwksUri(appUrl);
    const client = jwksClient({
        strictSsl: true,
        jwksUri: jwks_uri
    });
    const signing_key = await client.getSigningKey(decoded_access_token.header.kid);

    try {
        const verify = node_jwt.verify(access_token, signing_key.publicKey, { algorithms: ['RS256'] });
        res.send(JSON.stringify(verify))
    }
    catch(error) {
        res.send(error);  
    }
});

app.listen(port, () => {
    console.log(`server started on port ${port}`);
});
import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "regexp"
    "time"

    "github.com/lestrrat-go/jwx/jwk"
    "github.com/lestrrat-go/jwx/jwt"
)


var (
    authzHeaderRegexp = regexp.MustCompile("(?i)^Bearer (.*)$")
    baseAddress       = "https://<your_app_endpoint>"
)

type OIDCDiscoveryDocument struct {
    JWKSURI string `json:"jwks_uri"`
}

func FetchOIDCDiscoveryDocument(endpoint string) (*OIDCDiscoveryDocument, error) {
    resp, err := http.DefaultClient.Get(endpoint)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf(
            "failed to fetch discovery document: unexpected status code: %d",
            resp.StatusCode,
        )
    }

    var document OIDCDiscoveryDocument
    err = json.NewDecoder(resp.Body).Decode(&document)
    if err != nil {
        return nil, err
    }
    return &document, nil
}

func FetchJWK(baseAddress string) (jwk.Set, error) {
    doc, err := FetchOIDCDiscoveryDocument(
        baseAddress + "/.well-known/openid-configuration",
    )
    if err != nil {
        return nil, err
    }

    set, err := jwk.Fetch(context.Background(), doc.JWKSURI)
    return set, err
}

// DecodeUser parse request Authorization header and obtain user id and claims
func DecodeUser(r *http.Request) (string, map[string]interface{}, error) {
    // fetch jwks_uri from Authgear
    // you can cache the value of jwks to have better performance
    set, err := FetchJWK(baseAddress)
    if err != nil {
        return "", nil, fmt.Errorf("failed to fetch JWK: %s", err)
    }

    // get jwt token from Authorization header
    authzHeader := r.Header.Get("Authorization")
    match := authzHeaderRegexp.FindStringSubmatch(authzHeader)
    if len(match) != 2 {
        return "", nil, fmt.Errorf("no token")
    }

    // parse jwt token
    token, err := jwt.ParseString(match[1], jwt.WithKeySet(set))
    if err != nil {
        return "", nil, fmt.Errorf("invalid token: %s", err)
    }

    // validate jwt token
    err = jwt.Validate(token,
        jwt.WithClock(jwt.ClockFunc(
            func() time.Time { return time.Now().UTC() },
        )),
        jwt.WithAudience(baseAddress),
    )
    if err != nil {
        return "", nil, fmt.Errorf("invalid token: %s", err)
    }

    return token.Subject(), token.PrivateClaims(), nil
}

func handler(w http.ResponseWriter, r *http.Request) {
    // decode user example
    userid, claims, err := DecodeUser(r)
    isUserVerified, _ :=
        claims["https://authgear.com/claims/user/is_verified"].(bool)
    isAnonymousUser, _ :=
        claims["https://authgear.com/claims/user/is_anonymous"].(bool)

    // ... your handler logic
}
composer require firebase/php-jwt
composer require guzzlehttp/guzzle
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;

use Firebase\JWT\JWK;
use Firebase\JWT\Key;
use GuzzleHttp\Client;

$appUrl = ""; //place your authgear app endpoint here

function getJwksUri($appUrl) {
    $configEndpoint = $appUrl . "/.well-known/openid-configuration";
    $httpClient = new Client();
    $response = $httpClient->request('GET', $configEndpoint);
    $responseObject = json_decode($response->getBody());
    return $responseObject->jwks_uri;
}
$jwksUri = getJwksUri($appUrl);
$httpClient = new Client();
$jwksUriResponse = $httpClient->request('GET', $jwksUri);
$keysObject = json_decode($jwksUriResponse->getBody());

$jwks = (array) ($keysObject->keys)[0];

$parsedKey = JWK::parseKey($jwks, "RS256");
$signingKey = $parsedKey->getKeyMaterial();
if (!isset($_SERVER['HTTP_AUTHORIZATION']))
    throw new Exception("Invalid authorization header");
$authorizationHeader = $_SERVER['HTTP_AUTHORIZATION'];
$jwt = (explode(" ", $authorizationHeader))[1];
$decoded = JWT::decode($jwt, new Key($signingKey, 'RS256'));
echo json_encode($decoded);
JavaScript (Web)
Backend Integration
Forwarding to Authgear Resolver Endpoint
Validating JWT in your application server
Token-based (Native mobile or Single-page app)
Forwarding to Authgear Resolver Endpoint
Cookie-based (Website or Single-page app)
NGINX
Traefik
Apache APISIX
Traefik ForwardAuth middleware
http://nginx.org/en/docs/http/ngx_http_auth_request_module.html
https://github.com/authgear/authgear-server/blob/master/docs/specs/api-resolver.md
an example of how it looks
re-authentication
You can track the issue here

Add Passkeys Login

Passkeys give users a simple and secure way to sign in to your apps and websites across platforms without passwords.

Passkeys replace passwords and other passwordless login methods. It is built on the WebAuthn standard (also known as FIDO Sign-in), which uses public key cryptography to authenticate the user. With 1 click, Authgear upgrades your app to support this cutting-edge auth technology.

Platform support and Multi-devices

Users can log in to their accounts using their biometrics easily. On Apple devices, Touch ID and Face ID authorize the use of the passkey which then authenticates the user on the app or website.

Hardware security keys

Add Passkeys to your apps with Authgear

Authgear adds a passkey feature to your apps and websites instantly. To enable it:

  1. In your project portal, go to Authentication > Login Methods.

  2. In the Select Login Methods section, turn on the Enable passkey support for compatible devices. toggle.

  3. Press "Save" and your app now supports passkey login!

It will take time for the passkey technology to be available on everyone's devices. In the transition stage, it is recommended to enable "Password" or "Passwordless via Email/Phone" in your project so users with non-compatible devices can access your app.

If you want to use ONLY passkeys in your app, it's perfectly supported too! Select Custom and deactivate all authenticators in the Custom Login Methods tab. Remember to keep Enable Passkey support for compatible devices. turned on.

Support on different platforms

See the list of Passkey support via Authgear on different platforms.

  • macOS 12: Passkey is supported on major browsers. However, the credentials are deleted when clearing browser data.

  • iOS 15.5: Passkey is supported on Safari and stored locally a the device. Credential will be deleted by "Settings > Safari > Clear History and Website Data"

  • iOS 16 Beta 3: Passkey is synced with iCloud Keychain. The individual credentials can be viewed and managed in "Settings > Passwords"

  • Android 9 (API level 28) or higher: Supported.

Add WhatsApp OTP Login

Allow users to log into your app via OTP with WhatsApp, as a secure alternative to SMS

Authgear let your users login passwordlessly with WhatsApp OTP.

To enable this feature from the Portal:

  1. Go to Authentication > Login Methods, we are going make few changes on this page.

  2. In the top section of Select Login Methods, select Mobile.

  3. In Authentication of Select Login Methods, select Passwordless.

  4. In the tabs section below, switch to the tab Verification and OTP.

  5. In the dropdown Verify phone number by, select either WhatsApp or SMS or WhatsApp only.

  6. Press Save on the top left corner.

When the user login with their phone number, a WhatsApp message with an OTP and the app name will be received. They can copy the code by tapping on the "Copy code" button and log in by the code.

If "Verify phone number by WhatsApp or SMS" is enabled, the user can switch to receive the OTP via SMS instead in the login page.

Add Email Magic Link Login

Passwordless login with email links

Email Login Links, also known as "magic link", is a passwordless authentication method that allows users to log into a website or application without using a traditional password. Instead, it relies on a unique link sent to the user's email address.

Here's how it works:

  1. User initiates the login process by entering their email address on the login page.

  2. Authgear generates a unique, time-limited login link associated with the user's email address.

  3. The link is sent to the user's email inbox, with a button prompting them to click on it to log in.

  4. The user clicks on the link, and approve the login

  5. The user is securely logged in to the app or website.

Magic link login offers several advantages. It eliminates the need for users to remember and manage passwords, reducing the risk of weak or reused passwords. It also simplifies the login process and reduces friction, as users only need to access their email to authenticate.

To enable Email Login Links:

  1. In the Authgear Portal, go to "Authentication" > "Login Methods"

  2. Select "Email" or "Mobile/Email" as login methods

  3. Go to the "Verification and OTP" tab

  4. Under "Email", in the "Verify email by" field, select "Login Link"

Add Biometric Login

Overview

Biometric login is supported for the following operating systems:

  • iOS 11.3 or higher

  • Android 6.0 (API 23) or higher

Authgear supports enabling biometric login in the native mobile application. You will need to

  1. Enable biometric login in your application via the portal.

  2. In the mobile app, use the mobile SDK to enable biometric login for your users.

A pair of cryptographic keys will be generated upon registering biometric login. The private key will be stored securely in the device (using Keystore in Android and Keychain in iOS), while the public key is stored in the Authgear server. To authenticate the user, fingerprint or face is presented to unlock the private key, and a digital signed message is sent to the server to proof the authenticity of the user.

Fig 1.0. The following figure shows the sequence for enabling Biometric Login on a supported device:

The Client App that is already logged in to a user's account will check if biometrics is supported by the user's device. If the device supports biometric login, it is then enabled. The public key is sent to Authgear server and associated with the logged-in user's account.

The flow is then completed and biometric login is enabled for the user on the Client App.

Fig 2.0. The following figure shows the sequence for a user logging in with Biometric:

With biometric login already enabled for the user, the next time they need to log in they can initiate a biometric authentication flow which will follow the sequence shown in Fig 2.0 above. Once the biometric login is successful, Authgear server will return an access token and a refresh token. The client application can then use the access token to make authenticated requests.

Sounds overwhelming? Authgear's magic handles all these for you. Follow this guide to enable biometric login with a few lines of code in your app.

Enable biometric authentication for your project

  1. In the portal, go to Authentication > Biometric.

  2. Turn on Enable biometric authentication.

  3. Save the settings.

Set reasonably short token lifetimes for client applications

Biometric login is usually used when you want the user to re-login after a relatively short period of time. For sensitive applications such as financial apps, it's recommended to use a short refresh token lifetime and a short idle timeout.

  1. In the Authgear Portal, go to Applications

  2. Select the client application that represent the integration with the mobile app

  3. Set a short Refresh Token Lifetime to say 3,600 seconds (1 hour)

  4. Enable Expire after idling

  5. Set a short Idle Timeout, to say 1,800 seconds (30 minutes)

By doing so, the end-user's session will be expired 1 hour after their login, or after 30 minutes of inactivity. The end-user will need to authenticate themself again with biometric, even if the app process has not yet been killed.

Configure SDK so users must re-login after app closed

Apart from the short token lifetimes, it's also common for sensitive apps to ask the user to re-login by biometric after the app process is killed and relaunched.

The SDK should be configured to use TransientTokenStorage so the tokens are stored in memory, and will be cleared when the app is closed. So the end-users must authenticate with biometrics again.

Enable biometric login in mobile SDK

In the following section, we will show you how to use biometric login in the SDK. In the SDK code snippet, authgear is referring to the configured Authgear container.

Biometric options

In the SDKs, a set of biometric options is required to check the support or enable biometric on the device.

iOS

There are two options on iOS:

  • localizedReason is the message string the user will see when FaceID or TouchID is presented

  • constraint is an enum that constraint the access of key stored under different conditions:

    • biometryAny: The key is still accessible by Touch ID if fingers are added or removed, or by Face ID if the user is re-enrolled

    • BiometricCurrentSet: The key is invalidated if fingers are added or removed for Touch ID, or if the user re-enrolls for Face ID

  • policy can be used to allow users to log in with only biometrics, or using biometrics and the device PIN/password as fallback when biometric verification fails. The following are the available options:

    • BiometricLAPolicy.deviceOwnerAuthenticationWithBiometrics: When this policy is set, users can ONLY use a biometric method to complete the login. Users cannot log in with their device PIN/password after a failed biometric login attempt.

    • BiometricLAPolicy.deviceOwnerAuthentication: enable this policy to allow users to log in with non-biometric local authentication methods like device PIN/password when biometric verification fails or is not enrolled on their device.

Android

There are 6 options on Android:

  • title is the Title of the biometric dialog presented to the users

  • subtitle is the subtitle of the biometric dialog presented to the users

  • description is the description of the biometric dialog presented to the users

  • negativeButtonText is what the dismiss button says in the biometric dialog

Code examples

Check support

Always check if the current device supports biometric login before calling any biometric API, including before enabling biometric login and before using biometrics to login.

Enable biometric login

Enable biometric login for logged in user

Check if biometric has been enabled before

Before asking the user to log in with biometric, Check if biometric login has been enabled on the current device. I.e. Is the key pair exist on the device (Keystore in Android and Keychain in iOS).

This method will still return true even if all the fingerprint and facial data has been removed from the device. Before this method, you should use the "checkBiometricSupported" to check if biometry is supported in the device level.

Login with biometric credentials

If biometric is supported and enabled, you can use the Authenticate Biometric method to log the user in. If the key pair is invalidated due to changes in the biometry settings, e.g added fingerprint or re-enrolled face data, the biometricPrivateKeyNotFound will be thrown. You should handle the error by the Disable Biometric method, and ask the user to register biometric login again.

Disable biometric login on the current device

Error handling

In all methods related to biometric, the SDK may throw the following errors that describe the status of the biometry enrollment or the key pair stored on the device.

Biometric Verification Fallback Support

In some use cases, you may want to provide an alternative means for users to log in when biometric verification fails on their devices. For example, in a case where a user's finger is dirty (touch-based) or when the user's face is covered (Face ID).

Use of Device PIN/Password

In the biometric options, the parameters policy: BiometricLAPolicy.deviceOwnerAuthentication (iOS) and constraint BiometricAccessConstraintAndroid.DeviceCredential (Android) can be used to allow users to enter their device PIN/Password when biometric verification fails.

The biometric pop-up will look like this after a failed biometric log-in attempt with BiometricLAPolicy.deviceOwnerAuthentication policy on iOS:

With the BiometricLAPolicy.deviceOwnerAuthenticationWithBiometrics policy, the biometric login pop-up will not include the Enter Passcode button. An example is shown below:

Add Ethereum & NFT Login

Login with NFTs help developers build Web3 apps without blockchain knowledge

Sign In With Ethereum(also known as SIWE) introduces a new way of authenticating and identification of a user using their crypto-wallet addresses. Authgear saves you from all the complex setups and brings you the technology of the future with just a simple click.

Platform support

To make this as simple as possible, the following mainstream consumer-facing web3 providers are selected to be the gateway connecting your application and users.

These providers are typically supported by browsers with WebExtensions API, namely Chrome, Firefox, Edge, and Brave.

Supported NFTs

To assist you in building the greatest NFT-gated application ever, Authgear adds extra information to the user info that indicates whether the user owns NFT/NFTs of your selected NFT collection.

At the current stage, the following token types are supported:

Wallet address and NFTs in UserInfo

Here is an example of such user:

Add Sign In With Ethereum to your apps with Authgear

To enable "Sign In With Ethereum" to your apps and websites:

  1. In your project portal, go to "Authentication > Ethereum & NFT"

  2. Turn on the "Login With Ethereum" toggle

  3. Select your favourite blockchain network from the "Network" dropdown below

To prevent Web2 and Web3 identities being mixed together, Authgear has made it so that enabling "Sign In With Ethereum" would disable all your previously enabled identities and primary authenticators.

To go back to using Web2 authentication methods, you will have to disable "Sign In With Ethereum" and reconfigure your identities and authenticators.

Add NFT collections to your apps with Authgear

To populate user info with NFT tokens from the collections of your choice:

  1. In your project portal, go to "Authentication > Ethereum & NFT"

  2. Ensure "Login With Ethereum" toggle is checked

  3. Select the blockchain network from the "Network" for where your NFT collection is based on

  4. In the "NFT Collections" section, press "Add Collection", this will add an extra text field to the section

  5. Enter the contract address of the NFT collections in the "Contract Address" text field

  6. Select the token type of the contract address

  7. In the case of an ERC-1155 being selected, you will be prompted with a token tracking dialog

  8. Enter the desire token IDs and press "Continue"

  9. Press "Add" and you will see your collection is now in the pending collection list

If an error is shown that states that your NFT collection is not supported, it is possible that the collection has an alternative implementation of the ERC-721 or ERC-1155 standard

Once the collection starts being monitored, it will take a few minutes for Authgear to synchronize the NFT tokens for your users.

Forwarding authentication to Authgear Resolver Endpoint
Make sure "Issue JWT as access token" is enabled in your application

The passkey standard is supported on the latest versions of Chrome, Safari, and Firefox browsers. On iOS 16 and macOS 13 (Ventura), to the iCloud Keychain service. Passkeys are also (API level 28) or higher. A passkey is synchronized and relayed with an iCloud account and can be used across a user's devices.

Besides the built-in support of all major desktop and mobile platforms, passkeys can also be stored in hardware security keys such as , which provide the highest security against attacks.

See reference in Apple Developers Doc on and .

constraint is an array that defines the requirement of security level, which can be BIOMETRIC_STRONG, BIOMETRIC_WEAK, DEVICE_CREDENTIAL. See reference in Android developers documentation on

invalidatedByBiometricEnrollment is a boolean that controls if the key pair will be invalidated if a new biometric is enrolled, or when all existing biometrics are deleted. See reference in Android developers documentation on .

You can set the policy for iOS and constraint for Android in the of the Authgear SDK. The following is an example of a biometric options that allows users to use device's PIN/Password in iOS and Android:

The Sign In With Ethereum standard is built on the specification, which is typically performed on Web3 providers.

In the object of a user, the wallet address and the NFTs owned can be found.

Press "Save" then "Confirm" and now your app supports Sign in with Ethereum!

Press "Save" then "Confirm" and your app is now monitoring the NFT collection!

Apple has added passkey support
supported on Android 9
YubiKeys
authentication:
  identities:
    ...
    # Add biometric along with the other enabled identities
    - biometric
identity:
  biometric:
    # Enable listing biometric login in user setting page, default false
    list_enabled: true
let authgear = Authgear(
    clientId: "{your_clien_id}", 
    endpoint: "{your_app_endpoint}",
    tokenStorage: TransientTokenStorage())
authgear.configure() { result in
    switch result {
    case .success():
        // configured successfully
    case let .failure(error):
        // failed to configured
    }
}
public class MyAwesomeApplication extends Application {
    // The client ID of the oauth client.
    private static final String CLIENT_ID = "a_random_generated_string"
    // Deployed authgear's endpoint
    private static final String AUTHGEAR_ENDPOINT = "http://<myapp>.authgear.cloud/"
    private Authgear mAuthgear;
    public void onCreate() {
        super.onCreate();
        mAuthgear = new Authgear(this, CLIENT_ID, AUTHGEAR_ENDPOINT, new TransientTokenStorage());
        mAuthgear.configure(new OnConfigureListener() {
            @Override
            public void onConfigured() {
                // Authgear can be used.
            }

            @Override
            public void onConfigurationFailed(@NonNull Throwable throwable) {
                Log.d(TAG, throwable.toString());
                // Something went wrong, check the client ID or endpoint.
            }
        });
    }

    public Authgear getAuthgear() {
        return mAuthgear;
    }
}
import React, { useCallback } from "react";
import { View, Button } from "react-native";
import authgear, { TransientTokenStorage } from "@authgear/react-native";

function LoginScreen() {
  const onPress = useCallback(() => {
    // Normally you should only configure once when the app launches.
    authgear
      .configure({
        clientID: "client_id",
        endpoint: "http://<myapp>.authgear.cloud",
        tokenStorage: new TransientTokenStorage()
      })
      .then(() => {
        authgear
          .authenticate({
            redirectURI: "com.myapp.example://host/path",
          })
          .then(({ userInfo }) => {
            console.log(userInfo);
          });
      });
  }, []);

  return (
    <View>
      <Button onPress={onPress} title="Authenticate" />
    </View>
  );
}
Future<void> _init() async {
    _authgear = Authgear(
        endpoint: "ENDPOINT", 
        clientID: "CLIENT_ID", 
        tokenStorage: TransientTokenStorage()
    );
    await _authgear.configure();
}
import authgearCapacitor, { TransientTokenStorage, CancelError as CapacitorCancelError } from "@authgear/capacitor";
import authgearWeb, { SessionState, UserInfo, CancelError as WebCancelError } from "@authgear/web";
import { Capacitor } from "@capacitor/core";
import { useCallback, useState } from "react";

function isPlatformWeb(): boolean {
    return Capacitor.getPlatform() === "web";
}

const CLIENT_ID = "client_id";
const ENDPOINT = "http://<myapp>.authgear.cloud";

function AuthenticationScreen() {

    const [isAlertOpen, setIsAlertOpen] = useState(false);
    const [alertHeader, setAlertHeader] = useState("");
    const [alertMessage, setAlertMessage] = useState("");
    const [loading, setLoading] = useState(false);
    const [initialized, setInitialized] = useState(false);

    const [sessionState, setSessionState] = useState<SessionState | null>(() => {
        if (isPlatformWeb()) {
            return authgearWeb.sessionState;
        }
        return authgearCapacitor.sessionState;
    });

    const showError = useCallback((e: any) => {
        const json = JSON.parse(JSON.stringify(e));
        json["constructor.name"] = e?.constructor?.name;
        json["message"] = e?.message;
        let message = JSON.stringify(json);

        if (e instanceof WebCancelError || e instanceof CapacitorCancelError) {
            // Cancel is not an error actually.
            return;
        }

        setIsAlertOpen(true);
        setAlertHeader("Error");
        setAlertMessage(message);
    }, []);

    const postConfigure = useCallback(async () => {
        const sessionState = isPlatformWeb()
            ? authgearWeb.sessionState
            : authgearCapacitor.sessionState;
        if (sessionState !== "AUTHENTICATED") {
            setInitialized(true);
            return;
        }

        if (isPlatformWeb()) {
            await authgearWeb.fetchUserInfo();
        } else {
            await authgearCapacitor.fetchUserInfo();
        }

        setInitialized(true);
    }, []);

    const configure = useCallback(async () => {
        setLoading(true);
        try {

            if (isPlatformWeb()) {
                await authgearWeb.configure({
                    clientID: CLIENT_ID,
                    endpoint: ENDPOINT,
                    sessionType: "refresh_token",
                    isSSOEnabled: false,
                });
            } else {
                await authgearCapacitor.configure({
                    clientID: CLIENT_ID,
                    endpoint: ENDPOINT,
                    tokenStorage: new TransientTokenStorage()
                });

            }
            await postConfigure();
        } catch (e) {
            showError(e);
        } finally {
            setLoading(false);
        }
    }, [
        CLIENT_ID,
        ENDPOINT
    ]);
}
using System;

using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.OS;

using Xamarin.Forms;
using Authgear.Xamarin;

namespace MyApp.Droid
{
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            // ...

            var authgear = new AuthgearSdk(this, new AuthgearOptions
            {
                ClientId = CLIENT_ID,
                AuthgearEndpoint = ENDPOINT,
                TokenStorage = new TransientTokenStorage()
            });
            DependencyService.RegisterSingleton<AuthgearSdk>(authgear);
            LoadApplication(new App());

            // ...
        }

        // other methods are omitted for brevity.
    }
}
// check if current device supports biometric login
var supported = false
do {
    try authgear.checkBiometricSupported()
    supported = true
} catch {}

if supported {
    // biometric login is supported
}
boolean supported = false;
try {
    // biometric login is supported SDK_INT >= 23 (Marshmallow)
    if (Build.VERSION.SDK_INT >= 23) {
        // check if current device supports biometric login
        authgear.checkBiometricSupported(
                this.getApplication(),
                ALLOWED
        );
        supported = true;
    }
} catch (Exception e) {}
if (supported) {
    // biometric login is supported
}
// We will need the options for the other biometric api
const biometricOptions = {
  ios: {
    localizedReason: 'Use biometric to authenticate',
    constraint: 'biometryCurrentSet' as const,
  },
  android: {
    title: 'Biometric Authentication',
    subtitle: 'Biometric authentication',
    description: 'Use biometric to authenticate',
    negativeButtonText: 'Cancel',
    constraint: ['BIOMETRIC_STRONG' as const],
    invalidatedByBiometricEnrollment: true,
  },
};
// check if current device supports biometric login
authgear
    .checkBiometricSupported(biometricOptions)
    .then(() => {
        // biometric login is supported
    })
    .catch(() => {
        // biometric login is not supported
    });
// We will need the options for the other biometric api
final ios = BiometricOptionsIOS(
    localizedReason: "Use biometric to authenticate",
    constraint: BiometricAccessConstraintIOS.biometryAny,
);
final android = BiometricOptionsAndroid(
    title: "Biometric Authentication",
    subtitle: "Biometric authentication",
    description: "Use biometric to authenticate",
    negativeButtonText: "Cancel",
    constraint: [BiometricAccessConstraintAndroid.biometricStrong],
    invalidatedByBiometricEnrollment: false,
);

try {
    // check if current device supports biometric login
    await authgear.checkBiometricSupported(ios: ios, android: android);
    // biometric login is supported
} catch (e) {
    // biometric login is not supported
}
const biometricOptions: BiometricOptions = {
  ios: {
    localizedReason: "Use biometric to authenticate",
    constraint: BiometricAccessConstraintIOS.BiometryCurrentSet,
    policy: BiometricLAPolicy.deviceOwnerAuthenticationWithBiometrics,
  },
  android: {
    title: "Biometric Authentication",
    subtitle: "Biometric authentication",
    description: "Use biometric to authenticate",
    negativeButtonText: "Cancel",
    constraint: [BiometricAccessConstraintAndroid.BiometricStrong],
    invalidatedByBiometricEnrollment: true,
  },
};

const updateBiometricState = useCallback(async () => {
    if (isPlatformWeb()) {
      return;
    }

    try {
      await authgearCapacitor.checkBiometricSupported(biometricOptions);
     //enable biometric...
    } catch (e) {
      console.error(e);
    }
  }, []);

// We will need the options for the other biometric api
var ios = new BiometricOptionsIos
{
    LocalizedReason = "Use biometric to authenticate",
    AccessConstraint = BiometricAccessConstraintIos.BiometricAny,
};
var android = new BiometricOptionsAndroid
{
    Title = "Biometric Authentication",
    Subtitle = "Biometric authentication",
    Description = "Use biometric to authenticate",
    NegativeButtonText = "Cancel",
    AccessConstraint = BiometricAccessConstraintAndroid.BiometricOnly,
    InvalidatedByBiometricEnrollment = false,
};
var biometricOptions = new BiometricOptions
{
    Ios = ios, 
    Android = android
};
try
{
    // check if current device supports biometric login
    authgear.EnsureBiometricIsSupported(biometricOptions);
    // biometric login is supported
}
catch
{
    // biometric login is not supported
}
// provide localizedReason for requesting authentication
// which displays in the authentication dialog presented to the user
authgear.enableBiometric(
    localizedReason: "REPLACE_WITH_LOCALIZED_REASON",
    constraint: .biometryCurrentSet
) { result in
    if case let .failure(error) = result {
        // failed to enable biometric with error
    } else {
        // enabled biometric successfully
    }
}
// We will need the options for the other biometric api
BiometricOptions biometricOptions = new BiometricOptions(
    activity, // FragmentActivity
    "Biometric authentication", // title
    "Biometric authentication", // subtitle
    "Use biometric to authenticate", // description
    "Cancel", // negativeButtonText
    ALLOWED, // allowedAuthenticators
    true // invalidatedByBiometricEnrollment
);
authgear.enableBiometric(
    biometricOptions,
    new OnEnableBiometricListener() {
        @Override
        public void onEnabled() {
            // enabled biometric login successfully
        }

        @Override
        public void onFailed(Throwable throwable) {
            // failed to enable biometric with error
        }
    }
);
authgear
    .enableBiometric(biometricOptions)
    .then(() => {
        // enabled biometric login successfully
    })
    .catch((err) => {
        // failed to enable biometric with error
    });
try {
    await authgear.enableBiometric(ios: ios, android: android);
    // enabled biometric login successfully
} catch (e) {
    // failed to enable biometric with error
}
const enableBiometric = useCallback(async () => {
  setLoading(true);
  try {
    await authgearCapacitor.enableBiometric(biometricOptions);
  } catch (e: unknown) {
    showError(e);
  } finally {
    setLoading(false);
    await updateBiometricState();
  }
}, [showError, updateBiometricState]);

const onClickEnableBiometric = useCallback(
  (e: MouseEvent<HTMLIonButtonElement>) => {
    e.preventDefault();
    e.stopPropagation();

    enableBiometric();
  },
  [enableBiometric]
);
try
{
    await authgear.EnableBiometricAsync(biometricOptions);
    // enabled biometric login successfully
}
catch
{
    // failed to enable biometric with error
}
var enabled = (try? authgear.isBiometricEnabled()) ?? false
boolean enabled = false;
try {
    enabled = authgear.isBiometricEnabled();
} catch (Exception e) {}
authgear
    .isBiometricEnabled()
    .then((enabled) => {
        // show if biometric login is enabled
    })
    .catch(() => {
        // failed to check the enabled status
    });
try {
    final enabled = await authgear.isBiometricEnabled();
    // show if biometric login is enabled
} catch (e) {
    // failed to check the enabled status
}
try {
   const enabled = await authgearCapacitor.isBiometricEnabled();
} catch (e) {
      console.error(e);
}
try
{
    var enabled = await authgear.GetIsBiometricEnabledAsync();
    // show if biometric login is enabled
}
catch
{
    // failed to check the enabled status
}
authgear.authenticateBiometric { result in
    switch result {
        case let .success(userInfo):
            let userInfo = userInfo
            // logged in successfully
        case let .failure(error):
            // failed to login
        }
}
authgear.authenticateBiometric(
    biometricOptions,
    new OnAuthenticateBiometricListener() {
        @Override
        public void onAuthenticated(UserInfo userInfo) {
            // logged in successfully
        }

        @Override
        public void onAuthenticationFailed(Throwable throwable) {
            // failed to login
        }
    }
);
authgear
    .authenticateBiometric(biometricOptions)
    .then(({userInfo}) => {
        // logged in successfully
    })
    .catch((e) => {
        // failed to login
    });
try {
    final userInfo = await authgear.authenticateBiometric(ios: ios, android: android);
    // logged in successfully
} catch (e) {
    // failed to login
}
      const showUserInfo = useCallback((userInfo: UserInfo) => {
        const message = JSON.stringify(userInfo, null, 2);
        setIsAlertOpen(true);
        setAlertHeader("UserInfo");
        setAlertMessage(message);
      }, []);
      
      const authenticateBiometric = useCallback(async () => {
        setLoading(true);
        try {
          const { userInfo } = await authgearCapacitor.authenticateBiometric(
            biometricOptions
          );
          showUserInfo(userInfo);
        } catch (e: unknown) {
          showError(e);
        } finally {
          setLoading(false);
          await updateBiometricState();
        }
      }, [showError, showUserInfo, updateBiometricState]);
try
{
    var userInfo = await authgear.AuthenticateBiometricAsync(biometricOptions);
    // logged in successfully
}
catch
{
    // failed to login
}
do {
    try authgear.disableBiometric()
    // disabled biometric login successfully
} catch {
    // failed to disable biometric login
}
try {
    authgear.disableBiometric();
    // disabled biometric login successfully
} catch (Exception e) {
    // failed to disable biometric login
}
authgear
    .disableBiometric()
    .then(() => {
        // disabled biometric login successfully
    })
    .catch((err) => {
        // failed to disable biometric login
    });
try {
    await authgear.disableBiometric();
    // disabled biometric login successfully
} catch (e) {
    // failed to disable biometric login
}
  const disableBiometric = useCallback(async () => {
    setLoading(true);
    try {
      await authgearCapacitor.disableBiometric();
    } catch (e: unknown) {
      showError(e);
    } finally {
      setLoading(false);
      await updateBiometricState();
    }
  }, [showError, updateBiometricState]);
try
{
    await authgear.DisableBiometricAsync();
    // disabled biometric login successfully
}
catch
{
    // failed to disable biometric login
}
if let authgearError = error as? AuthgearError {
    switch authgearError {
    case .cancel:
        // user cancel
    case .biometricPrivateKeyNotFound:
        // biometric info has changed. e.g. Touch ID or Face ID has changed.
        // user have to set up biometric authentication again
    case .biometricNotSupportedOrPermissionDenied:
        // user has denied the permission of using Face ID
    case .biometricNoPasscode:
        // device does not have passcode set up
    case .biometricNoEnrollment:
        // device does not have Face ID or Touch ID set up
    case .biometricLockout:
        // the biometric is locked out due to too many failed attempts
    default:
        // other error
        // you may consider showing a generic error message to the user
    }
}
import com.oursky.authgear.BiometricLockoutException;
import com.oursky.authgear.BiometricNoEnrollmentException;
import com.oursky.authgear.BiometricNoPasscodeException;
import com.oursky.authgear.BiometricNotSupportedOrPermissionDeniedException;
import com.oursky.authgear.BiometricPrivateKeyNotFoundException;
import com.oursky.authgear.CancelException;


if (e instanceof CancelException) {
    // user cancel
} else if (e instanceof BiometricPrivateKeyNotFoundException) {
    // biometric info has changed
    // user have to set up biometric authentication again
} else if (e instanceof BiometricNoEnrollmentException) {
    // device does not have biometric set up
} else if (e instanceof BiometricNotSupportedOrPermissionDeniedException) {
    // biometric is not supported in the current device
    // or user has denied the permission of using biometric
} else if (e instanceof BiometricNoPasscodeException) {
    // device does not have unlock credential set up
} else if (e instanceof BiometricLockoutException) {
    // the biometric is locked out due to too many failed attempts
} else {
    // other error
    // you may consider showing a generic error message to the user
}
import {
    CancelError,
    BiometricPrivateKeyNotFoundError,
    BiometricNotSupportedOrPermissionDeniedError,
    BiometricNoEnrollmentError,
    BiometricNoPasscodeError,
    BiometricLockoutError,
} from '@authgear/react-native'

if (e instanceof CancelError) {
    // user cancel
} else if (e instanceof BiometricPrivateKeyNotFoundError) {
    // biometric info has changed. e.g. Touch ID or Face ID has changed.
    // user have to set up biometric authentication again
} else if (e instanceof BiometricNoEnrollmentError) {
    // device does not have biometric set up
    // e.g. have not set up Face ID or Touch ID in the device
} else if (e instanceof BiometricNotSupportedOrPermissionDeniedError) {
    // biometric is not supported in the current device
    // or user has denied the permission of using Face ID
} else if (e instanceof BiometricNoPasscodeError) {
    // device does not have unlock credential or passcode set up
} else if (e instanceof BiometricLockoutError) {
    // the biometric is locked out due to too many failed attempts
} else {
    // other error
    // you may consider showing a generic error message to the user
}
try {
    // ...
} on CancelException catch (e) {
    // user cancel
} on BiometricPrivateKeyNotFoundException catch (e) {
    // biometric info has changed. e.g. Touch ID or Face ID has changed.
    // user have to set up biometric authentication again
} on BiometricNoEnrollmentException catch (e) {
    // device does not have biometric set up
    // e.g. have not set up Face ID or Touch ID in the device
} on BiometricNotSupportedOrPermissionDeniedException catch (e) {
    // biometric is not supported in the current device
    // or user has denied the permission of using Face ID
} on BiometricNoPasscodeException catch (e) {
    // device does not have unlock credential or passcode set up
} on BiometricLockoutException catch (e) {
    // the biometric is locked out due to too many failed attempts
} catch (e) {
    // other error
    // you may consider showing a generic error message to the user
}
import {
    CancelError,
    BiometricPrivateKeyNotFoundError,
    BiometricNotSupportedOrPermissionDeniedError,
    BiometricNoEnrollmentError,
    BiometricNoPasscodeError,
    BiometricLockoutError,
} from '@authgear/capacitor'

if (e instanceof CancelError) {
    // user cancel
} else if (e instanceof BiometricPrivateKeyNotFoundError) {
    // biometric info has changed. e.g. Touch ID or Face ID has changed.
    // user have to set up biometric authentication again
} else if (e instanceof BiometricNoEnrollmentError) {
    // device does not have biometric set up
    // e.g. have not set up Face ID or Touch ID in the device
} else if (e instanceof BiometricNotSupportedOrPermissionDeniedError) {
    // biometric is not supported in the current device
    // or user has denied the permission of using Face ID
} else if (e instanceof BiometricNoPasscodeError) {
    // device does not have unlock credential or passcode set up
} else if (e instanceof BiometricLockoutError) {
    // the biometric is locked out due to too many failed attempts
} else {
    // other error
    // you may consider showing a generic error message to the user
}
try 
{
    // ...
}
catch (OperationCanceledException ex)
{
    // user cancel
}
catch (BiometricPrivateKeyNotFoundException ex)
{
    // biometric info has changed. e.g. Touch ID or Face ID has changed.
    // user have to set up biometric authentication again
}
catch (BiometricNoEnrollmentException ex)
{
    // device does not have biometric set up
    // e.g. have not set up Face ID or Touch ID in the device
}
catch (BiometricNotSupportedOrPermissionDeniedException ex)
{
    // biometric is not supported in the current device
    // or user has denied the permission of using Face ID
}
catch (BiometricNoPasscodeException ex)
{
    // device does not have unlock credential or passcode set up
}
catch (BiometricLockoutException ex)
{
    // the biometric is locked out due to too many failed attempts
}
catch
{
    // other error
    // you may consider showing a generic error message to the user
}
const biometricOptions: BiometricOptions = {
  ios: {
    localizedReason: "Use biometric to authenticate",
    constraint: BiometricAccessConstraintIOS.BiometryCurrentSet,
    policy: BiometricLAPolicy.deviceOwnerAuthentication,
  },
  android: {
    title: "Biometric Authentication",
    subtitle: "Biometric authentication",
    description: "Use biometric to authenticate",
    negativeButtonText: "Cancel",
    constraint: [BiometricAccessConstraintAndroid.BiometricStrong, BiometricAccessConstraintAndroid.DeviceCredential],
    invalidatedByBiometricEnrollment: true,
  },
};
{
  "x_web3": {
    "accounts": [
      {
        "account_identifier": {
          "address": "0xec7f0e0c2b7a356b5271d13e75004705977fd010"
        },
        "network_identifier": {
          "blockchain": "ethereum",
          "network": "1"
        },
        "nfts": [
          {
            "contract": {
              "name": "ExampleCollection",
              "address": "0x57f1887a8bf19b14fc0df6fd9b2acc9af147ea85",
              "type": "erc1155"
            },
            "tokens": [
              {
                "token_id": 1,
                "transaction_identifier": {
                  "hash": "0x1a2bed0813d524955926eb190018d9d8738836265b352e1c43dc2d5762f9c20B"
                },
                "block_identifier": {
                  "index": 12961059,
                  "timestamp": "2022-09-01T08:17:50Z"
                },
                "balance": "200"
              }
            ]
          }
        ]
      }
    ]
  }
}
Enable Biometric Login
Logging in with Biometric
🎉
🎉
biometryAny
biometryCurrentSet
BiometricManager.Authenticators
KeyGenParameterSpec.Builder
EIP-4361
MetaMask
ERC-721
ERC-1155
Biometric options
here

Add Anonymous Users

Allow guest users to use your apps and website and promote to regular users later.

Overview

You can use create an Anonymous User account for the guests in your apps, so they can carry out interactions just like a normal user. For example, guests can post comments and save preferences in your social platform before setting email and password. The user session will persist even if the app has been closed.

This improves the app experience because the user does not need to set up authenticators until further down the user journey, while still enjoying most of the app features. For app developers, the ability to create and assign Anonymous User also makes it easier to link the activities of an individual before and after sign-up.

Enable Anonymous User for your project

  1. In the portal, go to Authentication > Anonymous Users.

  2. Turn on Enable anonymous users.

  3. Save the settings.

Using the SDK

Sign up as an Anonymous User

This will create an Anonymous User for the session. Subsequent requests from the end-user in the session can be identified by the same sub

authgear
    .authenticateAnonymously()
    .then(({userInfo}) => {
        // Logged in as anonymous user successfully
    })
    .catch((err) => {
        // Handle the error
    });
try {
    final userInfo = await authgear.authenticateAnonymously();
    // Logged in as anonymous user successfully
} catch (e) {
    // Handle the error
}
authgear.authenticateAnonymously { result in
    switch result {
    case let .success(userInfo):
        // Logged in as anonymous user successfully
    case let .failure(error):
        // Handle the error
    }
}
mAuthgear.authenticateAnonymously(new OnAuthenticateAnonymouslyListener() {
    @Override
    public void onAuthenticated(@NonNull UserInfo userInfo) {
        // Logged in as anonymous user successfully
    }

    @Override
    public void onAuthenticationFailed(@NonNull Throwable throwable) {
        // Handle the error
    }
});
authgear
    .authenticateAnonymously()
    .then(({userInfo}) => {
        // Logged in as anonymous user successfully
    })
    .catch((err) => {
        // Handle the error
    });

Check the UserInfo object

UserInfo

{
  "sub": "...",
  "isVerified": false,
  "isAnonymous": true
}

Promotion of an Anonymous User

promoteAnonymousUser function can be called to promote an anonymous user to a regular user with login ID (e.g. email, phone number) and authenticators (e.g. password). The end-user will be prompted a sign up page to complete the promotion. The sub of an end-user will remain the same after promotion.

authgear
    .promoteAnonymousUser({
        redirectURI: THE_REDIRECT_URI,
    })
    .then(({userInfo}) => {
        // Promote anonymous user successfully
    })
    .catch((e) => {
        // Handle the error
    });
try {
    final userInfo = await authgear.promoteAnonymousUser(redirectURI: THE_REDIRECT_URI);
    // Promote anonymous user successfully
} catch (e) {
    // Handle the error
}
authgear.promoteAnonymousUser(
    redirectURI: THE_REDIRECT_URI
) { result in
    switch result {
    case let .success(userInfo):
        // Promote anonymous user successfully
    case let .failure(error):
        // Handle the error
    }
}
PromoteOptions options = new PromoteOptions(THE_REDIRECT_URI);
authgear.promoteAnonymousUser(options, new OnPromoteAnonymousUserListener() {
    @Override
    public void onPromoted(@NonNull UserInfo userInfo) {
        // Promote anonymous user successfully
    }
    @Override
    public void onPromotionFailed(@NonNull Throwable throwable) {
        // Handle the error
    }
});

Step 1: Start the promotion flow

When the user clicks promote on your website, make a start promotion call to redirect them to the promotion page.

authgear
    .startPromoteAnonymousUser({
        // Configure redirectURI which users will be redirected to
        // after they have promoted with Authgear.
        // You can use any path in your website.
        // Make sure it is in the "Redirect URIs" list of the Application.
        // The redirect uri for anonymous user promotion should be
        // different from the one for normal user authentication.
        // e.g. "https://yourdomain.com/promote-redirect"
        redirectURI: THE_REDIRECT_URI,
    })
    .then(({userInfo}) => {
        // Started the promotion flow
    })
    .catch((err) => {
        // Failed to start the promotion flow
    });

Step 2: Handle the promotion result

After the user promotes on the promotion page, the user will be redirected to the redirectURL with a code parameter in the URL query. In the redirectURI of your application, make a finish promotion call to handle the promotion result.

authgear
    .finishPromoteAnonymousUser()
    .then(({userInfo}) => {
        // Promoted successfully
        // You should redirect the user to another path
    })
    .catch((err) => {
        // Failed to finish promotion
    });
);

User Lifetime

Mobile apps

On Mobile SDKs, creating an anonymous user will create a key-pair. The key-pair is stored in the native encrypted store on the mobile device. The end-user can always re-login to the same anonymous user with the key-pair. Such anonymous user will become inaccessible when the encrypted store is removed.

Web apps and websites

On the Web SDK, there will be no key-pair created. Therefore the end-user will not be able to login to the same Anonymous User after the their session become invalid. For cookie-based authentication, it is controlled by the "idle timeout" and "session lifetime" of the Cookie. For token-based authentication, it is controlled by the "idle timeout" and "token lifetime" of the Refresh Token.

In other words, The anonymous user account lifetime is the same as the logged-in session lifetime.

To adjust the lifetime settings, change the timeouts and lifetimes in Portal > Applications accordingly.

Caution for high-traffic websites

You should create anonymous users only when necessary in the user journey to prevent creating excessive orphan accounts in your tenant.

How to Use the OAuth 2.0 State Parameter

Reference on what the OAuth 2.0 parameter is and how to use it in Authgear SDK.

The authorization server (Authgear) will include the value of the state parameter when redirecting the user-agent back to the client application. As a result, the client application can retrieve the value of state returned to verify that it is the origin of the authorization request.

In this post, we'll cover some possible usage of the state parameter and how to include the state parameter in an authorization request to the Authgear server.

Use cases of the State Parameter

The following are some use cases of the OAuth 2.0 state parameter.

1. Customize Post Login/Sign up User Experience

Because the value for the state parameter passed at the beginning of an authorization request is returned unchanged after authorization, you can use this behavior to customize the post-login or sign-up user experience.

For example, you can show users some custom messages after they sign up or log in, using a special link that was sent to them via email or SMS. The "special" thing in the link would be the value of a query parameter that can be passed in the state parameter.

Then, a client application can read the value of the state parameter and based on that, determine when and how to display the custom message or user experience.

2. Analytics

Another possible use of the state parameter is analytics and tracking user behavior. You can use the state token to include a unique key that tracks your campaigns. This way, you can know the number of users who sign up or log in to your application from a particular campaign.

3. Security: To Prevent Cross-site Request Forgery (CSRF)

Cross-site Request Forgery or short CSRF is a type of web security vulnerability where the attacker uses malicious means to trick a user into performing undesired actions on sites they use and trust. This type of attack usually targets users who are signed in and attempts to compromise access to their protected resources.

In OAuth, an attacker can perform a Cross-site Request Forgery using the client application's redirect URI. The attacker can trick a user into using a redirect URI that contains their authorization code or access token. Hence the user will end up using the access token and protected resources of the attacker. When they save new data using this access token, the attacker can also view them (as they are the original owner of the protected resources).

The official Authgear SDKs have mechanisms for protecting your applications from CSRF built into them.

However, if you are not using the official SDK, you can secure your application by generating a random hard-to-guess value on the client application and passing it in the state parameter. Your application should store this value securely on the user's client-side using session cookies or some other form of local storage. Then, verify the state parameter in the redirect URI against the value stored locally to confirm that a user-agent is the origin of an authorization request before exchanging the authorization code for an access token.

Examples: Including the State Parameter in Authorization Request

The following URL shows an example of an authorization request URL:

https://your_project.authgear.cloud/login?client_id=your_authgear_app_client_id&redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fauth-redirect&state=12345678

As you can see from the above URL, state is a query parameter in addition to other parameters like the client_id and redirect_uri.

If you're constructing the authorization URL manually, you can include the state parameter by simply appending "&state=random_state_value" to the authorization URL.

Alternatively, if you're using any of the Authgear SDKs, you can use the built-in state field to set a value.

The following code samples show the use of the state parameter with Authgear.

Step 1: Set up a React Project to use Authgear

First, install the Authgear web SDK by running the following command:

npm install @authgear/web

Next, configure Authgear in your React Project's index.tsx file like this:

import authgear from "@authgear/web";

export const endpoint = "https://your_project.authgear.cloud"; // The Authgear endpoint of your project e.g. https://my-app.authgearapps.com
export const clientID = ""; // Client ID can be obtained in the "Applications" page of the Portal

async function init() {
  try {
    await authgear.configure({
      endpoint,
      clientID,
      sessionType: "refresh_token",
    });
  } finally {
    createRoot(document.getElementById("react-app-root")!).render(<App />);
  }
}

// eslint-disable-next-line no-console
init().catch((e) => console.log(e));

Step 2: Include State Parameter in Authorization Request

Set the state field in your call to the startAuthentication() method of the Authgear SDK to a random hard-to-guess value based on your use case.

  const startLogin = useCallback(() => {
    authgear
      .startAuthentication({
        redirectURI: "http://localhost:4000/auth-redirect",
        prompt: PromptOption.Login,
        state: "12345678"
      })
      .then(
        () => {
          // started authorization, user should be redirected to Authgear
        },
        (err) => {
          // failed to start authorization
          console.error(err);
        }
      );
  }, []);

Step 3: Read and Use the Value of State Returned After the Authorization

Implement the component that handles your OAuth 2.0 redirect like this:

const AuthRedirect: React.FC = () => {
  const usedToken = useRef(false);

  const navigate = useNavigate();

  useEffect(() => {
    async function updateToken() {
      try {
        const u = new URL(window.location.href);
        const params = u.searchParams;
        const state = params.get("state") ?? undefined
        
        if (state !== undefined) {
          const initialState = "12345678"; // In a real app store the initial value on the client side using something like session cookies.
          //compare value of state returned in redirectURL to initial value set in startAuthentication()
          if (state === initialState) {
            //values match, do things log state to an analytic tool, set custom URL to navigate user to...
            console.log("state parameter match");
          } else {
            //the value for state param return does not match, do something like stopping the authentication
            console.log("state parameter dont match");
            return;
          }
        }
        
        await authgear.finishAuthentication();
      } finally {
        navigate("/");
        usedToken.current = true;
      }
    }

    if (!usedToken.current) {
      updateToken().catch((e) => console.error(e));
    }
  }, [navigate]);

  return <></>;
};

The above code will read the value of the state parameter returned in the redirect and compare it to the initial value.

For this example, when the initial value of the state parameter before authorization is not the same as the value returned in the redirectURL, we halt the authentication process.

Step 1: Set up PHP Project

composer require league/oauth2-client

Next, configure your PHP to use Authgear like this:

<?php
require 'vendor/autoload.php';
session_start(); 

$appUrl = "https://your_project.authgear.cloud";
$clientID = "";
$clientSecret = "";
$redirectUri = "http://localhost:8081/";

$provider = new \League\OAuth2\Client\Provider\GenericProvider([
    'clientId'                => $clientID,    // The client ID assigned to you by the provider
    'clientSecret'            => $clientSecret,    // The client password assigned to you by the provider
    'redirectUri'             => $redirectUri,
    'urlAuthorize'            => $appUrl . '/oauth2/authorize',
    'urlAccessToken'          => $appUrl . '/oauth2/token',
    'urlResourceOwnerDetails' => $appUrl . '/oauth2/userInfo',
    'scopes' => 'openid offline_access'
]);

if (!isset($_GET['code'])) {
    // Fetch the authorization URL from the provider; this returns the
    // urlAuthorize option and generates and applies any necessary parameters
    // (e.g. state).
    $authorizationUrl = $provider->getAuthorizationUrl();

    // Get the state generated for you and store it to the session.
    $_SESSION['oauth2state'] = $provider->getState();

    // Redirect the user to the authorization URL.
    header('Location: ' . $authorizationUrl);
    exit;
}

The League OAuth 2.0 client we are using in this example helps us generate random strings for the state parameter. In the above code, we store the value for the state generated in session on the line with $_SESSION['oauth2state'] = $provider->getState();.

Step 2: Read and Use the Value of State

Add an else block for the if (!isset($_GET['code'])) condition with the following code:

else {
    $code = $_GET['code'];

    if (empty($_GET['state']) || empty($_SESSION['oauth2state']) || $_GET['state'] !== $_SESSION['oauth2state']) {
        if (isset($_SESSION['oauth2state'])) {
            unset($_SESSION['oauth2state']);
        }

        exit('Invalid state');
    } else {
        try {
            $accessToken = $provider->getAccessToken('authorization_code', [
                'code' => $code
            ]);
            echo "Login successful ". $accessToken;
            
        } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
            // Failed to get the access token or user details.
            exit($e->getMessage());
        }
    }
}

The above code will prevent your PHP application from exchanging an authorization code for an access token when the value of state stored in the PHP session is not identical to the state returned in the redirect URI. The usage demonstrated above can prevent CSRF attacks.

Reauthentication

Authgear provides an easy method to reauthenticate the end-users. You can use this as a security measure to protect sensitive operations.

Overview

Your sensitive operation server endpoint MUST require the ID token. When you receive the ID token, you MUST verify the signature of it. If the signature is valid, you can trust the claims inside the ID token.

The auth_time claim in the ID token tells when was the end-user last authenticated. You should check the auth_time claim to see if the end-user was authenticated recently enough.

The https://authgear.com/claims/user/can_reauthenticate claim in the ID token tells whether the end-user can be reauthenticated. If the value of this claim is false, then depending on your business needs, you can either allow the end-user to proceed, or forbid the end-user to perform sensitive operations. The flows are illustrated by the following diagrams.

SDK Integration

The following code snippets illustrate the interaction between the SDK and Authgear.

const biometricOptions = {
  ios: {
    localizedReason: 'Use biometric to authenticate',
    constraint: 'biometryCurrentSet' as const,
  },
  android: {
    title: 'Biometric Authentication',
    subtitle: 'Biometric authentication',
    description: 'Use biometric to authenticate',
    negativeButtonText: 'Cancel',
    constraint: ['BIOMETRIC_STRONG' as const],
    invalidatedByBiometricEnrollment: true,
  },
};

async function onClickPerformSensitiveOperation() {
  // Step 1: Refresh the ID token to ensure the claims are up-to-date.
  await authgear.refreshIDToken();

  // Step 2: Check if the end-user can be reauthenticated.
  const canReauthenticate = authgear.canReauthenticate();
  if (!canReauthenticate) {
    // Step 2.1: Depending on your business need, you may want to allow
    // the end-user to proceed.
    // Here we assume you want to proceed.

    const idTokenHint = authgear.getIDTokenHint();

    // Step 2.2: Call the sensitive endpoint with the ID token.
    // It is still required to pass the ID token to the endpoint so that
    // the endpoint can know the end-user CANNOT be reauthenticated.
    return callMySensitiveEndpoint(idTokenHint);
  }

  // Step 3: The end-user can be reauthenticated.
  // If your app supports biometric authentication, you can pass
  // the biometric options to reauthenticate.
  // If biometric is enabled for the current user, it will be used instead.
  await authgear.reauthenticate({
    redirectURI: THE_REDIRECT_URI,
  }, biometricOptions);

  // Step 4: If we reach here, the reauthentication was done.
  // The ID token have up-to-date auth_time claim.
  const idTokenHint = authgear.getIDTokenHint();

  return callMySensitiveEndpoint(idTokenHint);
}
final ios = BiometricOptionsIOS(
    localizedReason: "Use biometric to authenticate",
    constraint: BiometricAccessConstraintIOS.biometryAny,
);
final android = BiometricOptionsAndroid(
    title: "Biometric Authentication",
    subtitle: "Biometric authentication",
    description: "Use biometric to authenticate",
    negativeButtonText: "Cancel",
    constraint: [BiometricAccessConstraintAndroid.biometricStrong],
    invalidatedByBiometricEnrollment: false,
);

Future<void> onClickPerformSensitiveOperation() async {
    // Step 1: Refresh the ID token to ensure the claims are up-to-date.
    await authgear.refreshIDToken();

    // Step 2: Check if the end-user can be reauthenticated.
    final canReauthenticate = authgear.canReauthenticate;
    if (!canReauthenticate) {
        // Step 2.1: Depending on your business need, you may want to allow
        // the end-user to proceed.
        // Here we assume you want to proceed.
        final idTokenHint = authgear.idTokenHint;

        // Step 2.2: Call the sensitive endpoint with the ID token.
        // It is still required to pass the ID token to the endpoint so that
        // the endpoint can know the end-user CANNOT be reauthenticated.
        return callMySensitiveEndpoint(idTokenHint);
    }

    // Step 3: The end-user can be reauthenticated.
    // If your app supports biometric authentication, you can pass
    // the biometric options to reauthenticate.
    // If biometric is enabled for the current user, it will be used instead.
    await authgear.reauthenticate(
        redirectURI: THE_REDIRECT_URI,
        biometricIOS: ios,
        biometricAndroid: android,
    );

    // Step 4: If we reach here, the reauthentication was done.
    // The ID token have up-to-date auth_time claim.
    final idTokenHint = authgear.idTokenHint;

    return callMySensitiveEndpoint(idTokenHint);
}
var ios = new BiometricOptionsIos
{
    LocalizedReason = "Use biometric to authenticate",
    AccessConstraint = BiometricAccessConstraintIos.BiometricAny,
};
var android = new BiometricOptionsAndroid
{
    Title = "Biometric Authentication",
    Subtitle = "Biometric authentication",
    Description = "Use biometric to authenticate",
    NegativeButtonText = "Cancel",
    AccessConstraint = BiometricAccessConstraintAndroid.BiometricOnly,
    InvalidatedByBiometricEnrollment = false,
};

async void OnPerformSensitiveOperationClicked(object sender, EventArgs args)
{
    // Step 1: Refresh the ID token to ensure the claims are up-to-date.
    await authgear.RefreshIdTokenAsync();

    // Step 2: Check if the end-user can be reauthenticated.
    var canReauthenticate = authgear.CanReauthenticate;
    if (!canReauthenticate)
    {
        // Step 2.1: Depending on your business need, you may want to allow
        // the end-user to proceed.
        // Here we assume you want to proceed.
        var idTokenHint = authgear.IdTokenHint;

        // Step 2.2: Call the sensitive endpoint with the ID token.
        // It is still required to pass the ID token to the endpoint so that
        // the endpoint can know the end-user CANNOT be reauthenticated.
        await CallMySensitiveEndpointAsync(idTokenHint);
        return;
    }

    // Step 3: The end-user can be reauthenticated.
    // If your app supports biometric authentication, you can pass
    // the biometric options to reauthenticate.
    // If biometric is enabled for the current user, it will be used instead.
    await authgear.ReauthenticateAsync(new ReauthenticateOptions
    {
        RedirectURI: THE_REDIRECT_URI,
    }, new BiometricOptions
    {
        Ios = ios,
        Android = android,
    });

    // Step 4: If we reach here, the reauthentication was done.
    // The ID token have up-to-date auth_time claim.
    var idTokenHint = authgear.IdTokenHint;
    await CallMySensitiveEndpointAsync(idTokenHint);
}
async function onClickPerformSensitiveOperation() {
  // Step 1: Refresh the ID token to ensure the claims are up-to-date.
  await authgear.refreshIDToken();

  // Step 2: Check if the end-user can be reauthenticated.
  const canReauthenticate = authgear.canReauthenticate();
  if (!canReauthenticate) {
    // Step 2.1: Depending on your business need, you may want to allow
    // the end-user to proceed.
    // Here we assume you want to proceed.

    const idTokenHint = authgear.getIDTokenHint();

    // Step 2.2: Call the sensitive endpoint with the ID token.
    // It is still required to pass the ID token to the endpoint so that
    // the endpoint can know the end-user CANNOT be reauthenticated.
    return callMySensitiveEndpoint(idTokenHint);
  }

  // Step 3: The end-user can be reauthenticated.
  // The end-user will be redirected to Authgear.
  // When the reauthentication finishes,
  // The end-user will be redirected back to the given redirect URI.
  await authgear.startReauthentication({
    redirectURI: THE_REDIRECT_URI
  });
}

// Suppose the following function is run when the end-user is redirected to
// the redirect URI
async function onRedirectAfterReauthentication() {
  // You HAVE to configure authgear again
  // because your website have been visited freshly.
  await authgear.finishReauthentication();
  await authgear.refreshIDToken();
  const idTokenHint = authgear.getIDTokenHint();
  return callMySensitiveEndpoint(idTokenHint);
}
func onClickPerformSensitiveOperation() {
    // Step 1: Refresh the ID token to ensure the claims are up-to-date.
    authgear.refreshIDToken() { result in
        switch result {
        case .success:
            // Step 2: Check if the end-user can be reauthenticated.
            let canReauthenticate = authgear.canReauthenticate
            if !canReauthenticate {
                // Step 2.1: Depending on your business need, you may want to allow
                // the end-user to proceed.
                // Here we assume you want to proceed.
                let idTokenHint = authgear.idTokenHint
                // Step 2.2: Call the sensitive endpoint with the ID token.
                // It is still required to pass the ID token to the endpoint
                // so that the endpoint can know the end-user CANNOT
                // be reauthenticated.
                callMySensitiveEndpoint(idTokenHint)
                return
            }

            // Step 3: The end-user can be reauthenticated.
            // By default biometric is used for reauthentication if it is enabled for the current user.
            // If you do not want biometric to be used, specify skipUsingBiometric: true
            authgear.reauthenticate(redirectURI: THE_REDIRECT_URI, skipUsingBiometric: false) { result in
                switch result {
                case .success:
                    // Step 4: If we reach here, the reauthentication was done.
                    // The ID token have up-to-date auth_time claim.
                    let idTokenHint = authgear.idTokenHint
                    callMySensitiveEndpoint(idTokenHint)
                    return
                case let .failure(error):
                    // Handle the error
                }
            }
        case let .failure(error):
            // Handle the error
        }
    }
}
public void onClickPerformSensitiveOperation() {
    BiometricOptions biometricOptions = new BiometricOptions(
        activity, // FragmentActivity
        "Biometric authentication", // title
        "Biometric authentication", // subtitle
        "Use biometric to authenticate", // description
        "Cancel", // negativeButtonText
        ALLOWED, // allowedAuthenticators
        true // invalidatedByBiometricEnrollment
    );

    // Step 1: Refresh the ID token to ensure the claims are up-to-date.
    authgear.refreshIDToken(new OnRefreshIDTokenListener() {
        @Override
        public void onFailed(Throwable throwable) {
            // Handle error
        }
        @Override
        public void onFinished() {
            // Step 2: Check if the end-user can be reauthenticated.
            boolean canReauthenticate = authgear.getCanReauthenticate();
            if (!canReauthenticate) {
                // Step 2.1: Depending on your business need, you may want to allow
                // the end-user to proceed.
                // Here we assume you want to proceed.
                String idTokenHint = authgear.getIDTokenHint();
                // Step 2.2: Call the sensitive endpoint with the ID token.
                // It is still required to pass the ID token to the endpoint
                // so that the endpoint can know the end-user CANNOT
                // be reauthenticated.
                callMySensitiveEndpoint(idTokenHint);
                return;
            }

            // Step 3: The end-user can be reauthenticated.
            // If your app supports biometric authentication, you can pass
            // the biometric options to reauthenticate.
            // If biometric is enabled for the current user, it will be used.
            ReauthenticateOptions options =
                new ReauthenticateOptions(THE_REDIRECT_URI);
            authgear.reauthenticate(options, biometricOptions, new OnReauthenticateListener() {
                @Override
                public void onFailed(Throwable throwable) {
                    // Handle error
                }
                @Override
                public void onFinished(UserInfo userInfo) {
                    // Step 4: If we reach here, the reauthentication was done.
                    // The ID token have up-to-date auth_time claim.
                    String idTokenHint = authgear.getIDTokenHint();
                    callMySensitiveEndpoint(idTokenHint);
                    return;
                }
            });
        }
    });
}

Reauthenticate conditionally by the last authentication time

If the end-users in your application often perform a series of sensitive operation, it is annoying that they have to reauthenticate themselves repeatedly before every operation. To allow the end-users to skip reauthentication if they have just reauthenticated themselves recently, the SDK allows you to inspect the last authentication time of the end-user.

async function onClickPerformSensitiveOperation() {
  await authgear.refreshIDToken();
  // Before you trigger reauthentication, check authTime first.
  const authTime = authgear.getAuthTime();
  if (authTime != null) {
    const now = new Date();
    const timeDelta = now.getTime() - authTime.getTime();
    if (timeDelta < 5 * 60 * 1000 /* 5 minutes */) {
      const idTokenHint = authgear.getIDTokenHint();
      return callMySensitiveEndpoint(idTokenHint);
    }
  }

  // Otherwise trigger authentication.
}
func onClickPerformSensitiveOperation() {
    authgear.refreshIDToken() { result in
        switch result {
        case .success:
            // Before you trigger reauthentication, check authTime first.
            if let authTime = authgear.authTime {
                let now = Date()
                let timeDelta = now.timeIntervalSince(authTime)
                if timeDelta < 5 * 60 {
                    let idTokenHint = authgear.idTokenHint
                    callMySensitiveEndpoint(idTokenHint)
                    return
                }
            }
            // Otherwise trigger authentication.
        case let .failure(error):
            // Handle the error
        }
    }
}
public void onClickPerformSensitiveOperation() {
    authgear.refreshIDToken(new OnRefreshIDTokenListener() {
        @Override
        public void onFailed(Throwable throwable) {
            // Handle error
        }
        @Override
        public void onFinished() {
            // Before you trigger reauthentication, check authTime first.
            Date authTime = authgear.getAuthTime();
            if (authTime != null) {
                Date now = new Date();
                long timedelta = now.getTime() - authTime.getTime();
                if (timedelta < 5 * 60 * 1000) {
                    String idTokenHint = authgear.getIDTokenHint();
                    callMySensitiveEndpoint(idTokenHint);
                    return;
                }
            }
            // Otherwise trigger authentication.
        }
    });
}
public async void OnPerformSensitiveOperationClicked(object sender, EventArgs args)
{
    await authgear.RefreshIdTokenAsync();
    var authTime = authgear.AuthTime;
    if (authTime != null)
    {
        var now = DateTimeOffset.UtcNow;
        var timedelta = now - authTime.Value;
        if (timedelta < TimeSpan.FromMinutes(5))
        {
            var idTokenHint = authgear.IdTokenHint;
            callMySensitiveEndpoint(idTokenHint);
            return;
        }
    }
}

Backend Integration

Finally in your backend, you have to verify the signature of the ID token, and then validate the claims inside.

import json
from contextlib import closing
from urllib.request import urlopen
from datetime import datetime, timezone, timedelta

import jwt
from jwt import PyJWKClient

base_address = "https://<your_app_endpoint>"

def fetch_jwks_uri(base_address):
    doc_url = base_address + "/.well-known/openid-configuration"
    with closing(urlopen(doc_url)) as f:
        doc = json.load(f)
    jwks_uri = doc["jwks_uri"]
    if not jwks_uri:
        raise Exception('Failed to fetch jwks uri.')
    return jwks_uri

def my_endpoint():
    id_token = GET_ID_TOKEN_FROM_HTTP_REQUEST_SOMEHOW()
    try:
        jwks_uri = fetch_jwks_uri(base_address)
        # Reuse PyJWKClient for better performance
        jwks_client = PyJWKClient(jwks_uri)
        signing_key = jwks_client.get_signing_key_from_jwt(id_token)
        claims = jwt.decode(
            id_token,
            signing_key.key,
            algorithms=["RS256"],
            audience=base_address,
            options={"verify_exp": True},
        )
        auth_time = claims["auth_time"]
        dt = datetime.fromtimestamp(auth_time)
        now = datetime.utcnow()
        delta = now - dt
        if delta > timedelta(minutes=5):
            raise ValueError("auth_time is not recent enough")
    except:
        # Handle error
        raise
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "time"

    "github.com/lestrrat-go/jwx/jwk"
    "github.com/lestrrat-go/jwx/jwt"
)

var (
    baseAddress = "https://<your_app_endpoint>"
)

type OIDCDiscoveryDocument struct {
    JWKSURI string `json:"jwks_uri"`
}

func FetchOIDCDiscoveryDocument(endpoint string) (*OIDCDiscoveryDocument, error) {
    resp, err := http.DefaultClient.Get(endpoint)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf(
            "failed to fetch discovery document: unexpected status code: %d",
            resp.StatusCode,
        )
    }

    var document OIDCDiscoveryDocument
    err = json.NewDecoder(resp.Body).Decode(&document)
    if err != nil {
        return nil, err
    }
    return &document, nil
}

func FetchJWK(baseAddress string) (jwk.Set, error) {
    doc, err := FetchOIDCDiscoveryDocument(
        baseAddress + "/.well-known/openid-configuration",
    )
    if err != nil {
        return nil, err
    }

    set, err := jwk.Fetch(context.Background(), doc.JWKSURI)
    return set, err
}

func CheckIDToken(idToken string) error {
    // fetch jwks_uri from Authgear
    // you can cache the value of jwks to have better performance
    set, err := FetchJWK(baseAddress)
    if err != nil {
        return fmt.Errorf("failed to fetch JWK: %s", err)
    }

    // parse jwt token
    token, err := jwt.ParseString(idToken, jwt.WithKeySet(set))
    if err != nil {
        return fmt.Errorf("invalid token: %s", err)
    }

    // validate jwt token
    err = jwt.Validate(token,
        jwt.WithClock(jwt.ClockFunc(
            func() time.Time { return time.Now().UTC() },
        )),
        jwt.WithIssuer(baseAddress),
    )
    if err != nil {
        return fmt.Errorf("invalid token: %s", err)
    }

    authTimeAny, ok := token.Get("auth_time")
    if !ok {
        return fmt.Errorf("no auth_time")
    }

    authTimeUnix, ok := authTimeAny.(float64)
    if !ok {
        return fmt.Errorf("auth_time is not number")
    }

    authTime := time.Unix(int64(authTimeUnix), 0)
    now := time.Now().UTC()

    diff := now.Sub(authTime)
    if diff > 5*time.Minute {
        return fmt.Errorf("auth_time is not recent enough")
    }

    return nil
}

Add authentication to any web page

Learn how to add authentication to any web page without using Authgear's SDKs with IIFE(Immediately-invoked Function Expression) bundle

Prerequisites

Create a basic web server

Start with making a new folder on your computer to keep the app’s source code (In the example, we call it authgear-spa-js-login). Then, initialize a new NPM project by running the following command:

npm init -y

Next, we install two required packages:

npm install express
npm install -D nodemon

Next, open the package.json file and edit scripts entry to have start and dev commands like the below:

{
  // ...
  "scripts": {
    "start": "node server.js",
    "dev": "nodemon server.js"
  },
  // ...
}

Now you can run the app in two modes: prod and dev.

For example, npm run dev will run the application using nodemon, monitoring for changes as we modify files.

Creating server.js

Create a new file server.js in the root of the project and populate it with the following code:

const express = require("express");
const { join } = require("path");
const app = express();

// Serve static assets from the /public folder
app.use(express.static(join(__dirname, "public")));

// Endpoint to serve the configuration file
app.get("/authgear_config.json", (req, res) => {
  res.sendFile(join(__dirname, "authgear_config.json"));
});

// Serve the index page for all other requests
app.get("/*", (_, res) => {
  res.sendFile(join(__dirname, "index.html"));
});

// Listen on port 3000
app.listen(3000, () => console.log("Application running on port 3000"));

Create a basic HTML page

Create a index.html file in the root of the project and add the following content to the created file:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Authgear SPA SDK Sample</title>
    <link rel="stylesheet" type="text/css" href="/css/main.css" />
  </head>

  <body>
    <h2>SPA Authentication Sample</h2>
    <p>Welcome to our page!</p>
    <button id="btn-login" disabled="true" onclick="login()">Log in</button>
    <button id="btn-logout" disabled="true" onclick="logout()">Log out</button>
    <script src="js/app.js"></script>
    <script src="<https://unpkg.com/@authgear/web@2.2.0/dist/authgear-web.iife.js>"></script>
  </body>
</html>
<script src="<https://unpkg.com/@authgear/web@2.2.0/dist/authgear-web.iife.js>"></script>

Create a main.css file

Create a new folder called public folder in the project root folder and create another folder called css inside the public folder. Add a new file in there called main.css. This will be used to determine how the log-in and log-out button elements will be hidden on the main page depending on whether a user is authenticated or not.

Open the newly-created public/css/main.css file and add the following CSS:

.hidden {
    display: none;
}
  
label {
    margin-bottom: 10px;
    display: block;
}

After creating an HTML file and applying CSS styles, see now how our page looks like by running npm run dev and accessing it at http://localhost:3000.

Create an app.js file

To add some action to the page, we create a new directory in the public folder called js, and add a new file there called app.js. Copy and paste the following JS code that reads authgear_config.json file Authgear app-specific values (endpoint and clientId) from the endpoint using fetchAuthConfig function. Also, it configures a new Authgear client, and defines login and logout logic:

let authgearClient = null;

const fetchAuthConfig = () => fetch("/authgear_config.json");

const configureClient = async () => {
    const response = await fetchAuthConfig();
    const config = await response.json();
    authgearClient = window.authgear.default;

    await authgearClient.configure({
        endpoint: config.endpoint,
        clientID: config.clientID,
        sessionType: "refresh_token",
    }).then(
        () => {
            console.log("Authgear client successfully configured!");
        },
        (err) => {
            console.log("Failed to configure Authgear");
        }
    );
};

const login = async () => {
    await authgearClient
        .startAuthentication({
            redirectURI: window.location.origin,
            prompt: "login",
        })
        .then(
            () => {
                console.log("Logged in!");
            },
            (err) => {
                console.log("Log in failed", err);
            }
        );
};

const logout = () => {
    authgearClient
    .logout({
      redirectURI: window.location.origin,
    })
    .then(
      () => {
        console.log("Logged out successfully");
      },
      (err) => {
        console.log("Failed to logout");
      }
    );
};

window.onload = async () => {
    await configureClient();
    updateUI();

    const query = window.location.search;
    if (query.includes("code=")) {

        updateUI();

        window.history.replaceState({}, document.title, "/");
    }
}

const updateUI = async () => {
    const isAuthenticated = authgearClient.sessionState === "AUTHENTICATED";

    document.getElementById("btn-logout").disabled = !isAuthenticated;
    document.getElementById("btn-login").disabled = isAuthenticated;
};

Understanding the whole picture

Let’s breakdown down app.js code in the previous section and understand how authentication is achieved with Authgear:

Configure the Authgear client

fetchAuthConfig: Firstly, this function makes a request to the /authgear_config.json the endpoint we exposed in server.js to fetch Authgear app setting values from authgear_config.jsonfile.

configureClient: Once we retrieve the configuration information for the Authgear client from the authgear_config.json file and we set up the Authgear client with these settings. It also logs a message to the console, informing whether the configuration was successful or not.

Login flow

login: The function is called by the Login button previously defined on the HTML page. It performs the login action by calling authgearClient.startAuthentication Authgear’s function. It redirects the user to the Auhthgear login page. After the user logs in successfully, they will be redirected back to the same page we set in redirectURI. Run the project and click the Login button. You should be taken to the Authgear Login Page configured for your application.

After authenticating successfully, you will be redirected to the page you were before.

Logout flow

Update the UI

window.onload: This is a function that runs when the page loads. It configures the Authgear client and updates the UI. If the page's URL contains a "code=" it means the user is authenticated (code the query will be received from the Authgear server), it updates the UI again and removes the "code=" from the URL.

Evaluate the authentication state

updateUI: This function updates the status of the login and logout buttons based on whether the user is authenticated or not. In Authgear, you can check if the user has logged in or not with sessionState the attribute. If the user is authenticated, we disable the login button and enable the logout button, and vice versa if the user is not authenticated.

Passwordless Login for Apple App Store Review

How to pass the Apple Store review process if your app uses passwordless login.

However passwordless login via email/phone OTP cannot be used in the review because the reviewer do not have access to the email inbox or phone number of that demo account.

You can create a demo account with email/phone and password by turning password on temporarily. In the project portal:

  1. Go to Authentication > Login Methods.

  2. In Select Login Methods, select Custom.

  3. In the tabs section below, select the tab Custom Login Methods.

  4. In Custom Login Methods, activate Password.

  5. Go to User Management, press Add User in the command bar.

  6. Create the demo user by entering the email address and password

  7. Go to where you were in Step 4, deactivate Password.

  8. Now you can login as the demo user in your app with the email and password.

  9. Submit your app for review with the credentials.

Enable Two-Factor Authentication (2FA)

Guide on how to add Two-Factor Authentication to your application.

Authgear supports Two-Factor Authentication (2FA) or Multi-Factor Authentication (MFA) for additional layers of security in your application.

When you enable MFA on your application, Authgear will require your users to present two or more factors in order to log in. These factors could be their password and a One-time Password (OTP) that is sent to their registered email address or phone number. As a result, an attacker can not gain access to a user's account with only a compromised password.

In this post, you'll learn how to enable MFA or 2FA for your Authgear project and how to configure 2FA grace period.

Pre-requisites

  • An Authgear Project.

1. How to Enable 2FA

Step 1: Open 2FA Settings Page

You can enable 2FA and configure other settings from the 2-Factor Authentication page in Authgear Portal.

To open the 2-Factor Authentication page, log in to Authgear Portal, select your project, then navigate to Authentication > 2FA.

Step 2: Select a 2FA Requirements Policy

Next, use the 2FA Requirements dropdown on the 2-Factor Authentication page to set when to require users to use 2-Factor Authentication to sign in.

The available options are:

  • Disabled: When this is selected, 2FA will not be required to log in for any user, including users who already have 2FA set up for their account.

  • Optional: This policy will only require 2FA to log in for users who already have 2FA set up for their account. Users who have not set up 2FA can continue to log in without it.

Toggle the Show "Do not ask again on this device" for 2FA switch on if you wish to require 2FA only the first time a user logs in from a specific device.

Step 3: Add Available 2-Factor Methods

The Available 2-Factor sub-section on the 2-Factor Authentication page shows a list of supported second-factor authentication methods. The supported methods include:

  • Google Authenticator/Authy

  • Additional Password

  • OTP Code/Login Link via Email

  • OTP Code via Phone

Check the box for each 2FA method you wish to enable for your project.

Use the up and down allows on the right of each method to order the priority of the 2FA methods.

Once you're done, click on the Save button at the top-left of the 2-Factor Authentication page to keep your new settings.

2. Grace Period in Mandatory 2FA

The 2FA Grace Period feature grants your users some time to set up 2FA for their accounts. This is very helpful for the Mandatory enforcement of 2FA.

The following are the two types of 2FA grace periods you can set for your Authgear project:

Global Grace Period: When this type of grace period is enabled, all users who do not have 2FA set up for their account will be asked to set up 2FA the next time they log in. When the Global Grace Period is disabled, users who have not set up 2FA for their account cannot log in. Instead, they'll get an error message requesting them to contact an admin.

Individual Grace Period: This is a type of grace period that is set per user. It grants a user 10 days to set up 2FA for their account. This is ideal for allowing individual users to set up 2FA when the Global Grace Period is disabled.

How to roll out Mandatory 2FA

The following steps show how to roll out Mandatory 2FA using grace periods:

  1. Change 2FA requirement policy to Mandatory

  2. Enable Global Grace Period so that all users who haven't set up 2FA are required to do so the next time they login.

  3. Use your own channel to notify user's about the duration of the global grace period you've decided.

  4. Disable the Global Grace Period once the date you notified users of has passed. After you do this, users that still haven't set up 2FA will be unable to log in.

Step 1: Enable Global Grace Period

To enable the Global Grace Period, navigate to Authentication > 2FA in the Authgear Portal. Then, set 2FA Requirements to Mandatory so that you can view the Enable global grace period switch.

Toggle the Enable global grace period switch on so that your users without 2FA will be required to set up 2FA the next time they log in. Or set Enable global grace period off, if you do not want users without 2FA to log in, or set up 2FA without contacting an admin.

Step 2: Enable Individual Grace Period

When you set the 2FA requirement for your project to Mandatory and Global Grace Period is turned off, you can still use the individual grace period to grant a specific user a grace period to set up 2FA for their account.

To set individual grace period, navigate to User Management > User in Authgear Portal. Then, select the user you wish to set individual grace period for by clicking on the row with their ID in your project's users' list.

From the selected user's details page, click on the Account Security tab, then the Grant grace period to set up 2FA button. You will see a prompt to confim your action, click Confirm to continue.

The duration of the individual grace period is 10 days. However, you can extend or cancel it from the user's details page.

Token-based (Native mobile or Single-page app)

Authenticate incoming request by access token in the HTTP header.

By using Authgear, you can add the login feature to your mobile native app and single-page application easily. Authgear supports various authentication methods, that you can easily turn on and configure in the portal.

Overview

How it works

Your app server will receive a request with the access token

Verify request in your app server

To verify the request in your app server, you can choose to Forward authentication to Authgear Resolver Endpoint or Verify JSON Web Token (JWT) in your app server.

Request Example

> GET /api_path HTTP/1.1
> Host: yourdomain.com
> Authorization: Bearer <AUTHGEAR_ACCESS_TOKEN>

Get Started

The following tutorials show you how to add user login to your native mobile or single-page app using Authgear.

1. Frontend Integration

Choose your platform below:

2. Backend Integration

Use Authgear as an OpenID Connect Provider

Using Authgear as an OpenID Connect Provider for any OIDC compatible applications.

If your application supports logging in using an OpenID Connect provider, you can use Authgear as the provider.

Setting up Authgear in the Portal

  1. Go to Applications on the left menu bar.

  2. Click ⊕Add Application in the top tool bar.

  3. Input the name and select the application type OIDC Client Application. Click "Save".

  4. You will see a link to this guide that can help you for setting up, then click "Next".

  5. In the URIs section, fill in the Authorized Redirect URIs with your application's redirect uri.

  6. Obtain the OpenID Connect configuration:

    1. You can obtain the Client ID and Client Secret from the Basic Info section.

    2. You can obtain the OIDC Endpoints from the Endpoints section.

  7. Provide the OpenID Connect configuration to your application.

🎉 Done! You should be able to use Authgear to log in to your application.

WordPress Example

In this section, we are going to demonstrate how to use Authgear as the OIDC provider for WordPress login.

  1. Go to Setting > OpenID Connect Client.

  2. Fill in the form

    1. Client ID: Obtain the Client ID from the Basic Info section.

    2. Client Secret Key: Obtain the Client Secret from the Basic Info section.

    3. OpenID Scope: Space separated list of scopes the plugin could access.

      • Example: openid offline_access https://authgear.com/scopes/full-userinfo.

      • https://authgear.com/scopes/full-userinfo is needed to obtain user's profile (e.g. email). Otherwise the plugin will be able to get the user id only.

    4. Login Endpoint URL: Obtain Authorization Endpoint from the Endpoints section.

      • Example: https://{AUTHGEAR_APP_DOMAIN}/oauth2/authorize.

    5. Userinfo Endpoint URL: Obtain Userinfo Endpoint from the Endpoints section.

      • Example: https://{AUTHGEAR_APP_DOMAIN}/oauth2/userinfo.

    6. Token Validation Endpoint URL: Obtain Token Endpoint from the Endpoints section.

      • Example: https://{AUTHGEAR_APP_DOMAIN}/oauth2/token.

    7. End Session Endpoint URL: Keep it empty.

    8. Identity Key: Where in the user claim to find the user's identification data.

      • Suggest to use sub which is the user id in Authgear.

    9. Setup the user claim keys based on your project login method setting.

      • If your project is using email to login

        • Nickname Key: Set it to email.

        • Email Formatting: Set it to {email}.

      • If your project is using phone to login

        • Nickname Key: Set it to phone_number.

        • Email Formatting: Clear it.

      • If your project is using username to login

        • Nickname Key: Set it to preferred_username.

        • Email Formatting: Clear it.

  3. At the bottom of the plugin settings page, you will be able to obtain the Redirect URI. Go to Authgear portal, add the uri to the Authorized Redirect URIs.

Set Password Expiry

Settings for requiring users to reset their password if they haven't logged in after specific number of days

You can set up your Authgear project such that a user's password expires after a specific number of days. When a user logs in after the password expiry date, they'll see a prompt to change their password before they're redirected back to your app.

In this post, you'll learn how to set the Password Expiry feature in the Authgear Portal.

Step 1: Enable Password Expiry

To enable password expiry, first, log into the Authgear portal, select your project then navigate to Authentication > Login Methods. Next, select a Login method that supports password, then switch to the Passwords tab and scroll to the Password Expiry section. Toggle the "Force password change on next login if it has expired" button to enable password expiry.

Step 2: Set Expiry Date

You can use the text field labeled Force change since last update (days) to specify the number after which a user's password should expire. The value should be the number of days in the future from the last date the user set or updated their password. For example, setting the value to 90 means the user's password will expire 90 days later from the last date they set or updated their password.

Once you're done, click on the Save button at the top of the page to keep your changes.

SSO with Mobile App / Web SPA

If you are building token-based websites or mobile apps, you can enable the SSO feature via the SDK.

When SSO-enabled is ON, the end-user will need to enter their authentication credentials when they login to the first app. Later on, when they login to the second app, they will see a continue screen so that they can log in with just a click, without authenticating themselves again.

It is important that when the SSO feature is ON, don't set the prompt parameter when authenticating (e.g. prompt=login), it will force to show the login screen.

When the end-user logout the SSO-enabled app, all the apps will be logged out at the same time.

You can turn on this feature when you configure the SDK by setting the is sso enabled option to true.

These type of SSO requires sharing the cookies between mobile apps and the system browsers on mobile, hence underlying it use ASWebAuthenticationSession on iOS and Custom Tab on Android, which will show a popup box like this:

Single Sign-on

Provide a seamless user experience across multiple applications with the single sign-on feature.

Single sign-on (SSO) is defined as login once, logged in all apps. If you have multiple mobile apps or websites that wants to streamline the user experiences. You can configure your apps to turn on the SSO feature, so the end-users only have to enter their authentication credentials once.

There are multiple ways to achieve Single Sign-on, with various pros-and-cons:

Setup local development environment for Cookie-based authentication

Setting up the local development environment for websites that use cookie-based authentication.

This guide is only for cookie-based authentication in local development setups. A typical scenario is developing websites. If you are developing mobile applications which use token-based authentication, you can just skip this guide and continue with it as usual.

Problems using localhost as a local website domain

Authgear sets a cookie in the browser inside the project domain. When running your application on localhost, the browser will not see the cookies because the website is not in the subdomain of the domain in which the cookies are set. Therefore, the browser will not be able to authenticate itself.

Setup a new Authgear project

For local development, it is highly recommended to create a new application on Authgear before continuing to the rest of the guide.

  1. Go to the Application tab in your dashboard

  2. Add your local application domain {SUBDOMAIN}.{PROJECT_NAME}.authgear.cloud under the Allowed Origins list

  3. Add an application, name it whatever you want. DO NOT check the Issue JWT as access token box because we are using cookie-based authorization.

  4. Put your redirect URI for login and logout under the Redirect URIs list and Post Logout Redirect URIs list respectively.

Map domain in hosts

To make the cookies visible to the browser, the local website domain has to be inside the domain where the cookies are set.

By adding the following line to the /etc/hosts file on the local machine, we can point the application domain name to localhost.

The browser will be able to see the auth cookies if visiting the website via this domain.

Use HTTPS

Although you can see the cookies now, the cookies have the Secure attribute set. To include them in an HTTP request, the request has to be transmitted over a secure channel (HTTPS in most browsers). Therefore, we also need to establish HTTPS connections for our browser with the server.

Generate certificates

A key file and a cert file will be generated. They will be used in the next part of the guide.

Using nginx

We will need an nginx server to serve the certificate and enable SSL.

Add the following config file to your nginx/conf.d directory, or mount it to a volume together with the cert and key if you are using nginx in docker.

The examples below show the nginx config files for nginx in host and nginx in docker.

Docker host network driver is not supported in Docker Desktop, it has to be in a bridge network. If your nginx in docker needs to proxy requests to services in your host network, it needs to resolve host.docker.internal through 127.0.0.11. If your services are also in the same docker bridge network (i.e. same docker-compose without specifying multiple networks), the destination domain will be the container name.

Finish

Now visit the website through https://<yourapp>.authgear.cloud, and the browser will be able to send requests with the authorization cookies.

Forgot/Reset Password settings

Learn how to configure different options for password reset/account recovery.

The Forgot/Reset Password settings tab allows you to configure the behavior of the account recovery process for your Authgear project to meet your specific needs. For example, you can use this feature to determine whether to deliver recovery code to users via SMS, WhatsApp, or email.

In this post, you'll learn the various configurations available via the Password Settings tab and how to navigate to the page.

1. How to Navigate to the Password Settings Page

To access the Password Settings page, log in to your Authgear account, select your project, and then navigate to Authentication > Login Methods.

Next, select your current Login Method (Email, Mobile, Mobile/Email, or Custom). The login method you select affects the options available for you to customize.

Scroll down to just below the Select Login Methods section and click on the Password tab to reveal the Password settings screen.

Note: Make sure the login method you select has password enabled (you can not view the password settings screen if you only enable Passwordless login).

2. Enable Reset Password by Phone Number

When you enable password reset by phone number for your project, users will receive an OTP code that they can enter in the AuthUI to finish the account recovery flow.

To able this feature, first in the Password Settings tab, select a Login Method that supports Mobile (E.g Mobile or Mobile/Email methods) and has the password option enabled.

Next, click on the "Reset password with phone by" dropdown then select how you want to send the OTP from the available options. The available options include SMS, WhatsApp, and WhatsApp or SMS.

Once you're done save your changes to enable the new configuration.

The next time your users try to reset their password using their phone number as the login ID, they should see a screen like this to enter the OTP sent to their phone:

3. Reset by Email using OTP Instead of Link

If you prefer your users receive an OTP that they can enter in the AuthUI instead of a recovery link that they would normally click, you can use this password recovery settings to enable that.

To enable this setting, click on the "Reset password with email by" dropdown in the Password Settings tab. Then, select the One-time Password (OTP) option. Save your changes to enable the feature.

How to Use Social/Enterprise Login Providers Without AuthUI

Learn how to take users directly to an external OAuth provider's authorization page without opening AuthUI login page.

You can use Authgear's x_oauth_provider_alias parameter to add social/enterprise login to your application without showing any AuthUI pages. To do this, you must enable the Social/Enterprise only login method for your project in Authgear Portal.

In this post, you'll learn how to use the x_oauth_provider_alias parameter to skip AuthUI and take users directly to a social/enterprise login provider's authorization page.

Pre-requisite

What We Will Build

  • In this post, we'll walk through the steps for adding only the social/enterprise login method to an Authgear application.

  • We'll use the Authgear SDK for React Native to set the x_oauth_provider_alias parameter and show how to use x_oauth_provider_alias without the SDK in an example Express app.

The sequence diagram above demonstrates the flow for using x_oauth_provider_alias to skip AuthUI.

First, when the user clicks on the sign-in button, your application will call your Authgear project's authorize endpoint with the x_oauth_provider_alias parameter appended.

Next, when Authgear server receives the call, it redirects to the third-party OAuth (Social/EnterpriseLogin) provider's authorization server. The user is then shown the OAuth provider's login/authorization page for them to grant authorization. Once that is done, the OAuth provider returns an authorization code to Authgear.

In the next step, Authgear exchanges the authorization code for an access token, refresh token, and ID token and then starts creating a new user or logging the existing user in.

The rest of the flow from there involves the usual sending of the authorization code to the client application and the client application exchanging the authorization code for an access token, refresh token, and ID token.

Step 1: Configure a Social/Enterprise Login Provider

The first step is to add the Social/Enterprise login provider you wish to use to your Authgear project. For our example, we'll be adding Facebook.

To add a new provider, log in to Authgear Portal, select your project, then navigate to Authentication > Social/Enterprise Login.

Next, click on the Edit button, then enter the Client ID and Client Secret for the Social/Entreprise login provider then click Save. Also, note the value for Alias as you'll use it in a later step.

Step 2: Enable Social/Enterprise Only Login Method

An important step for making Authgear to skip AuthUI is to enable the Social/Enterprise only login method. By doing this, Authgear will understand that the only login method your app will use is from a third-party OAuth provider. As a result, it's ok to skip showing AuthUI for login, registration, or login method selection and go to the OAuth provider's authorization page directly.

To enable Social/Enterprise only, navigate to Authentication > Login Methods. Next, select the Social/Enterprise only Login Method and click Save.

Step 3: Set x_oauth_provider_alias Parameter

Now that you've set up everything to allow your application to use only Social/Enterprise Login, you can open Authgear's authorize endpoint with the x_oauth_provider_alias parameter to start an authorization request that will skip AuthUI.

We will show 2 ways to do this. The first is using the SDK and the second is by passing x_oauth_provider_alias as a URL query parameter.

1. Adding x_oauth_provider_alias using Authgear SDK

The following example shows how to add x_oauth_provider_alias using the Authgear React Native SDK:

Note that the value for oauthProviderAlias must be the Alias for the social/enterprise provider you configured in step 1.

2. Add x_oauth_provider_alias to the Authorization URL

You can manually add x_oauth_provider_alias parameter to the Authgear authorization endpoint when you're not using the Authgear SDK.

The following example shows how to add x_oauth_provider_alias to the Authgear authorization endpoint:

The above code will append &x_oauth_provider_alias=facebook to the authorization URL.

App2App Login

Perform faster authentication flow via another app installed on the same device.

This may be familiar for users from UK, which many neobanks are using the app2app mechanism to authorize the money transfer from 1 bank app to another.

The App2App mechanism allows one app to authenticate the user using another apps connected to the auth server installed on the same device. This is achieved by universal links and the apps do not need to share the session via the system browser or the refresh tokens via the token storage.

  • The session cannot be shared via the browser cookies

  • The session cannot be shared via a common token storage

Mechanism

An app can start the authentication flow by opening a link to another app, instead of using the authorization endpoint. The app which handles the link should validate the authentication request, then could return a valid authorization code. The valid code is then transferred to the original app using universal link. The initiating app can use that authorization code to perform code exchange for tokens with Authgear.

Setting it up in Authgear

Configuration in the authorizing app

  1. Go to the Application detail page of the authorizing app, i.e. the app which handles the app2app authentication requests.

  2. Scroll to the bottom and you will see the App2App config panel.

  3. Migration mode offers a less secure mechanism which helps older user sessions to participate in App2App. DO NOT enable it unless there is migration problem.

Configuration in the initiating app

  1. Go to the Application detail page of the initiating app, i.e. the app which initiates the app2app authentication requests.

  2. In the redirect URIs, a universal link that's capable of opening this app should be set.

Setting up the apps

  1. Define and set up the universal links for both apps, for example:

    1. https://a.example.com/authorize should open the authorizing app (App A)

    2. https://b.example.com/redirect should open the initiating app (App B)

  2. In App B, call startApp2AppAuthentication(options: App2AppAuthenticateOptions) to initiate the app2app login

    • App2AppAuthenticateOptions.authorizationEndpoint should be an url of an universal link pointing to App A, i.e. https://a.example.com/authorize

    • App2AppAuthenticateOptions.redirectUri should be an URI for the authorizing app to return the authentication result. It must be an universal link which opens the current app. i.e. https://b.example.com/redirect

  3. In App A, upon receiving the app2app login request

    • Call parseApp2AppAuthenticationRequest(url: URL): App2AppAuthenticateRequest?

    • The result will be null if the url is not a valid app2app request.

  4. You can approve or reject the app2app request in App A

    • Approve: approveApp2AppAuthenticationRequest(request: App2AppAuthenticateRequest)

      • Approves an app2app request returning the result through the redirect URI.

      • request should be the return value of parseApp2AppAuthenticationRequest.

      • This method must be called when then SDK session state is AUTHENTICATED, and the current session supported app2app authentication by providing a device_key, or else an error will be thrown.

    • Reject: rejectApp2AppAuthenticationRequest(request: App2AppAuthenticateRequest, error: Error)

      • Rejects an app2app request, returning an error through the redirect URI.

      • request should be the return value of parseApp2AppAuthenticationRequest.

      • error is the reason to reject the request.

  5. When it's back to App B, call handleApp2AppAuthenticationResult(url: URL)

    • This method should be called by the app which initiate the app2app authentication flow, and when received the result through the universal link, url should be the URL of the universal link received.

After "signing up" as an anonymous user, you can and see the sub of the end-user.

The includes an optional state parameter. The value of the state parameter can be any random string or number defined by a client application (e.g. a web or mobile that uses Authgear for user authentication) before making an authorization request. In fact, the state parameter is added to the authorization URL as a URL query.

You can also use the value you specify in the state parameter in an analytic tool (for example, as id in the identify(id) function) to track user's behavior pre-login and post-login.

To learn more about using the state parameter for tracking user behavior, see our detailed guide .

Create a new React project or use an existing project and configure the project to use Authgear. The following example is based on our .

This example uses the PHP package. Install the package using the following command:

Reauthentication in Authgear is built on top of the . The ID token is a JWT.

Sequence diagram for end-user who CANNOT reauthenticate
Sequence diagram for end-user who CAN reauthenticate

In this guide, you'll make a simple website server to host the SPA app using . We'll also use it to serve our HTML page and any assets it needs, like JavaScript, CSS, and so on. You can also view a on the GitHub repo.

Before we start, ensure you have Node.js installed in your system. If not, download and install it from the .

An Authgear account: You need an Authgear account to follow this guide. If you don't have one, you can on the Authgear website.

A Registered App: You need a registered application type (Single Page Application) in Authgear. Follow the guide and skip part. You will retrieve the Authgear Web SDK from Authgear's CDN using IIFE(Immediately-invoked Function Expression) bundle and reference a script in our HTML directly.

Also, install so that our server can be restarted automatically on any code changes in dev mode:

We do not use a package manager such as , we will retrieve the Authgear Web SDK from Authgear's CDN using IIFE(Immediately-invoked Function Expression) bundle. We can reference a script in our HTML directly:

You can install the Authgear Web SDK as a dependency of your application, it is useful if you are building React or React Native apps. See how to .

Go ahead and create a new user or log in using an email (we specified the Passwordless Email login method in the first part). When you try to log in with your email, you should receive a to your email box to confirm login operation.

logout: This function logs the user out and redirects them back to the original page (at). It uses Authgear’s logout function and logs a message to the console indicating the result of the operation.

When you try to publish a mobile app on the Apple AppStore, there will be an . You need provide a demo user account for the reviewers to access the features of the app.

An Authgear account. Create one for free .

And basic experience with Authgear.

Mandatory: Use the mandatory policy to require 2FA for all users. That means users who have not set up 2FA will not be able to log in if no grace period is set. To use this option, consider further actions like .

When users that could not set up their 2FA during the Global Grace Period contact you (the admin), enable individual grace period for them using the instructions in .

Forwarding authentication to Authgear Resolver Endpoint
Verify JSON Web Token (JWT) in your app server

Follow the previous section () to setup an OIDC Client Application.

We are going to use plugin . Or you can use any other OIDC compatible plugin. Download and activate it in your WordPress site.

By default, password expiry is turned off for your Authgear project. shows that forcing users to change their password after some time can do more harm than good.

If you want to avoid the said popup box, you will need to use WKWebView on iOS and WebKitWebView on Android for UIImplementation instead; And use for sharing login session between mobile apps, and between mobile and web instead.

Related Feature
Technical Remarks

is not trivial. This guide provides a simple way to bootstrap your local application that communicates with the production Authgear server.

You can learn more .

Log in and create a new project on

One quick simple way to do this is to use , you may follow the installation steps . After installing mkcert, generate a certificate with the following command:

In the above examples, nginx will also authenticate requests by creating sub-requests to the Authgear internal endpoint. You can learn more .

For implementing login and logout logic in your website, please refer to .

An Authgear account. Create one for free .

See our guide for instructions on how to get a Client ID and Client Secret for Facebook Login.

The key thing about using the above option is the presence of oauthProviderAlias: 'facebook' in the authenticate() method of the Authgear SDK. This parameter tells Authgear to redirect directly to an OAuth provider, given that the Social/Enterprise provider is configured properly as shown in . Also, the Social/Enterprise only Login method is enabled.

This is an Enterprise feature, please contact us for using the App2App flow in your project at

Please note that this is not the Single Sign-on feature, if your are offering multiple apps under the same brand and wish the users to use a shared login session among their apps in the device, you may want to use instead. App2app should be used when:

A detailed explanation on the technology can be found in .

This is an Enterprise feature, please contact us for enabling the App2App flow in your project at

Select Enable App2App login for this Application"

OAuth 2.0 framework
Mixpanel
here
React example Git repository
League OAuth 2.0 client
OIDC ID token
ExpressJS
full-source code
official website
create it for free
nodemon
Webpack
install the package
magic link
http://localhost:3000
App Review process
here
getting started
JavaScript (Web)
React Native SDK
Android SDK
iOS SDK
Flutter SDK
Xamarin SDK
Backend Integration
OpenID Connect Generic Client
setting up a grace period for rollout
step 2
Setting up Authgear in the Portal
setup application
installing the Authgear Web SDK
authgear.configure({
    clientID: CLIENT_ID,
    endpoint: ENDPOINT,
    sessionType: "refresh_token",
    isSSOEnabled: true,
});
authgear.configure({
    clientID: CLIENT_ID,
    endpoint: ENDPOINT,
    isSSOEnabled: true,
});
final authgear = Authgear(
    clientID: CLIENT_ID,
    endpoint: ENDPOINT,
    isSsoEnabled: true,
);
var authgearOptions = new AuthgearOptions
{
    ClientId = CLIENT_ID,
    AuthgearEndpoint = ENDPOINT,
    IsSsoEnabled = true,
};
// Android
#if __ANDROID__
var authgear = new AuthgearSdk(GetActivity().ApplicationContext, authgearOptions);
#else
#if __IOS__
var authgear = new AuthgearSdk(UIKit.UIApplication.SharedApplication, authgearOptions);
#endif
#endif
Authgear(
    clientId: CLIENT_ID,
    endpoint: ENDPOINT,
    isSSOEnabled: true,
)
new Authgear(
    getApplication(),
    CLIENT_ID,
    ENDPOINT,
    new PersistentTokenStorage(getApplication()),
    true // isSsoEnabled = true
);
127.0.0.1 {SUBDOMAIN}.{PROJECT_NAME}.authgear.cloud
mkcert *.{PROJECT_NAME}.authgear.cloud
server {
  listen       443 ssl;
  server_name  {SUBDOMAIN}.{PROJECT_NAME}.authgear.cloud;

  ssl_certificate      /path/to/your/cert;
  ssl_certificate_key  /path/to/your/key;

  location / {
    # Change it to your service endpoint
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;

    auth_request /_auth;
    auth_request_set $x_authgear_session_valid $upstream_http_x_authgear_session_valid;
    auth_request_set $x_authgear_user_id $upstream_http_x_authgear_user_id;
    auth_request_set $x_authgear_user_anonymous $upstream_http_x_authgear_user_anonymous;
    auth_request_set $x_authgear_user_verified $upstream_http_x_authgear_user_verified;
    auth_request_set $x_authgear_session_acr $upstream_http_x_authgear_session_acr;
    auth_request_set $x_authgear_session_amr $upstream_http_x_authgear_session_amr;
    auth_request_set $x_authgear_session_authenticated_at $upstream_http_x_authgear_session_authenticated_at;
    auth_request_set $x_authgear_user_can_reauthenticate $upstream_http_x_authgear_user_can_reauthenticate;

    proxy_set_header x-authgear-session-valid $x_authgear_session_valid;
    proxy_set_header x-authgear-user-id $x_authgear_user_id;
    proxy_set_header x-authgear-user-anonymous $x_authgear_user_anonymous;
    proxy_set_header x-authgear-user-verified $x_authgear_user_verified;
    proxy_set_header x-authgear-session-acr $x_authgear_session_acr;
    proxy_set_header x-authgear-session-amr $x_authgear_session_amr;
    proxy_set_header x-authgear-session-authenticated-at $x_authgear_session_authenticated_at;
    proxy_set_header x-authgear-user-can-reauthenticate $x_authgear_user_can_reauthenticate;
  }

  location /_auth {
    internal;
    resolver 8.8.8.8;
    set $resolver https://{PROJECT_NAME}.authgear.cloud/_resolver/resolve;
    proxy_pass $resolver;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
  }
}
server {
  listen       443 ssl;
  server_name  {SUBDOMAIN}.{PROJECT_NAME}.authgear.cloud;

  ssl_certificate      /path/to/your/cert;
  ssl_certificate_key  /path/to/your/key;

  location / {
    resolver 127.0.0.11;
    # change {CONTAINER_NAME} to host.docker.internal if accessing host
    proxy_pass http://{CONTAINER_NAME}:{PORT};
    proxy_set_header Host $host;

    auth_request /_auth;
    auth_request_set $x_authgear_session_valid $upstream_http_x_authgear_session_valid;
    auth_request_set $x_authgear_user_id $upstream_http_x_authgear_user_id;
    auth_request_set $x_authgear_user_anonymous $upstream_http_x_authgear_user_anonymous;
    auth_request_set $x_authgear_user_verified $upstream_http_x_authgear_user_verified;
    auth_request_set $x_authgear_session_acr $upstream_http_x_authgear_session_acr;
    auth_request_set $x_authgear_session_amr $upstream_http_x_authgear_session_amr;
    auth_request_set $x_authgear_session_authenticated_at $upstream_http_x_authgear_session_authenticated_at;
    auth_request_set $x_authgear_user_can_reauthenticate $upstream_http_x_authgear_user_can_reauthenticate;

    proxy_set_header x-authgear-session-valid $x_authgear_session_valid;
    proxy_set_header x-authgear-user-id $x_authgear_user_id;
    proxy_set_header x-authgear-user-anonymous $x_authgear_user_anonymous;
    proxy_set_header x-authgear-user-verified $x_authgear_user_verified;
    proxy_set_header x-authgear-session-acr $x_authgear_session_acr;
    proxy_set_header x-authgear-session-amr $x_authgear_session_amr;
    proxy_set_header x-authgear-session-authenticated-at $x_authgear_session_authenticated_at;
    proxy_set_header x-authgear-user-can-reauthenticate $x_authgear_user_can_reauthenticate;
  }

  location /_auth {
    internal;
    resolver 8.8.8.8;
    set $resolver https://{PROJECT_NAME}.authgear.cloud/_resolver/resolve;
    proxy_pass $resolver;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
  }
}
authgear
  .configure({
    clientID: '<YOUR_CLIENT_ID>',
    endpoint: '<YOUR_AUTHGEAR_PROJECT_ENDPOINT>',
  })
  .then(() => {
    authgear
      .authenticate({
        redirectURI: 'com.reactnativeauth://host/path',
        oauthProviderAlias: 'facebook',
      })
      .then(({userInfo}) => {
        Alert.alert('Login successful, welcome ' + userInfo.email);
      });
  });
app.get("/login", (req, res) => {
  const url = new URL("<YOUR_AUTHGEAR_PROJECT_ENDPOINT>/oauth2/authorize");
  url.searchParams.set('client_id', config.client.id);
  url.searchParams.set('redirect_uri', "http://localhost:3000");
  url.searchParams.set('scope', "openid offline_access");
  url.searchParams.set('x_oauth_provider_alias', 'facebook')

  res.redirect(url);

});
authgear portal password expiry
App2App flow in iOS
Recent security research
App2App Login
Pre-authenticated URLs
Running a local Authgear server
https://portal.authgear.com/
mkcert
here
here
Web SDK
here
here
https://www.authgear.com/talk-with-us
Single Sign-on
this specification
https://www.authgear.com/talk-with-us
here
step 1
Demo of the App2App login flow

Social Login / Enterprise Login Providers

Add third-party identity providers to enable frictionless sign in for your users

Authgear supports the following social and enterprise identity providers. Please click the link below for setup instructions.

Social Login Providers

Guides on how to add social login providers like Facebook, Google, LinkedIn Apple

Pre-authenticated URLs

Use the pre-authenticated URLs feature to open a website from a native app in an authenticated state.

Pre-authenticated URLs is a feature that enables single sign-on (SSO) from a mobile application to a website. It allows users who are authenticated on a mobile application to open a website in an authenticated state.

An example use case for a pre-authenticated URL is opening a web application in a WebView.

Pre-requisites

To use pre-authenticated URLs, you must have the following:

  • An Authgear application of type Native app.

  • A second Authgear application that has pre-authentication URLs enabled.

How to Implement Pre-authentication URLs in your application

Step 1: Enable SSO in Native App client

First, ensure your mobile application uses an Authgear application with the Native App.

Your application must also enable SSO to allow pre-authenticated URLs to work. You can enable SSO by isSSOEnabled: true in the configure() method of Authgear SDK.

authgear
  .configure({
    clientID: '<CLIENT_ID>',
    endpoint: '<AUTHGEAR_PROJECT_URL>',
    isSSOEnabled: true,
  })

Step 2: Add Allowed Origin to Web App Client

Next, add an allowed origin to the web application client in Authgear. Navigate to Applications in the Authgear Portal, select the web application client, and scroll to the Allowed Origins section. Then, add the origin you wish to use for Pre-authentication URLs. Note that the origin should be of the format "protocol (scheme) + domain + port". For example, if the mobile application wants to open https://www.mywebapp.com/home?key=value, the origin must be https://www.mywebapp.com.

Step 3: Generate Pre-Authenticated URL

The Pre-Authenticated URL is a link that the Authgear SDK can generate for a mobile client that has the Pre-Authenticated URLs feature enabled. Your mobile application can open the Pre-Authenticated URL in a web view for users to start browsing the origin in an authenticated state.

To generate the Pre-Authenticated URL, call the makePreAuthenticatedURL() method of the Authgear SDK as shown below:

const url = await authgear.makePreAuthenticatedURL({
    webApplicationClientID: "YOUR_WEB_APP_CLIENT_ID", // Replace with you web app client id
    webApplicationURI: "YOUR_WEB_APP_URI", // Replace with you web app uri
  });

The makePreAuthenticatedURL() method accepts an object as a parameter. Inside the object, you should provide your web application's client ID and redirect URI.

The URL in YOUR_WEB_APP_URI should be a page on the web application that calls the authenticate() method of Authgear SDK with isSSOEnabled: true (or a page that initiates an authorization request) .

Step 4: Open Pre-Authenticated URL in a WebView

After the makePreAuthenticatedURL() return the URL, your mobile application should open the URL in a WebView. From there, users should be able to continue their current authenticated session (from the mobile app) on the web application.

The following code sample shows how to open the pre-authenticated URL using the Linking.openURL() method of React Native.

Linking.openURL(url).catch(err =>
      console.error("Couldn't load page", err),
    );

The user will see a "Continue Screen" and will not need to enter their credentials again to log in.

Force Authgear to Show Login Page

Force Authgear to always show login page even if the user have already logged in.

When user login / signup to Authgear, it usually starts with your application making a request to the authorization endpoint, which leads to a login or signup screen.

If the user is already signed in on the browser, the Single Sign On feature will show a "Continue Screen" instead as follows.

If your application do not want to utilize the Single Sign On feature, and always show the login / sign up screen instead, you can force Authgear to show login page by using prompt="login" at the authorize endpoint.

How to Force Authgear to Show Login Page

The following code shows how to set prompt: "login" in Authgear SDKs:

authgear
  .startAuthentication({
    redirectURI: "<AUTHGEAR_REDIRECT_URI>",
    prompt: PromptOption.Login,
  })
authgear
  .authenticate({
    redirectURI: 'com.reactnativeauth://host/path',
    prompt: PromptOption.Login,
  })
AuthenticateOptions options = new AuthenticateOptions("<AUTHGEAR_REDIRECT_URI>");
List<PromptOption> promptOptions = Arrays.asList(PromptOption.LOGIN);
options.setPrompt(promptOptions);
mAuthgear.authenticate(options, new OnAuthenticateListener() {
    @Override
    public void onAuthenticated(@Nullable UserInfo userInfo) {
        
    }

    @Override
    public void onAuthenticationFailed(@NonNull Throwable throwable) {
        Log.d(TAG, throwable.toString());
    }
});
authgear?.authenticate(
    redirectURI: "<AUTHGEAR_REDIRECT_URI>",
    prompt: "login"
)
_authgear.authenticate(
        redirectURI: "<AUTHGEAR_REDIRECT_URI>",
        prompt: "login",
      );

Single Sign-On with SAML

Guides on how to use Authgear as a SAML Identity Provider

SAML allows the Identity Provider and Service Provider to authenticate and authorize without exchanging a user's password.

  • The Service Provider (SP): In SAML, this is the service that trust the Identity Provider to handle the process of user authentication.

  • The Identity Provider (IdP): handles user authentication and notifies the Service Provider once the user is authenticated.

Authgear supports the SAML protocol. Hence, you can set up third-party services like Salesforce, Dropbox, Figma, etc. to trust Authgear with the user authentication process.

Specific Instructions for Service Providers

See the following guides for some popular service providers:

  • Use Authgear as SAML Identity Provider for Salesforce

  • Use Authgear as SAML Identity Provider for Dropbox

How to Set up SAML in Authgear

To set up SAML in Authgear, you need to create an Authgear client application with the Application Type: OIDC/SAML Client. Then use the configuration for the Authgear client application to configure a SAML IdP on the Service Provider's platform.

The following steps show more details on how to set up an OIDC/SAML Client Application in Authgear Portal.

Step 1: Create Authgear Client Application

Log in to Authgear Portal, then click on Applications from the navigation menu.

Click on Add Application to create a new client application. Or select an existing client application with the OIDC/SAML Client type.

Enter a Name for the application and select OIDC/SAML Client Application as the Application Type.

Click Save to proceed.

Step 2: Enable SAML 2.0

By default, the SAML 2.0 Configuration is disabled for the client application.

Click on the SAML 2.0 tab then toggle SAML 2.0 Support switch to enable SAML 2.0.

You'll be required to enter at least one Allowed Assertion Consumer Service URLs (ACS URLs) before you can save your changes. Hence, get an ACS URL from the Service Provider you plan to use.

Step 3: Configure Authgear as IdP on a Service Provider

Visit the portal for the Service Provider you plan to use and add Authgear as an Identity Provider using the SAML configuration from your Authgear client application.

Refer to the following instructions for a generic SP:

Configuration on SP:

  • Enter the Identity Provider Metadata URL provided by Authgear if it's supported by the SP. e.g. https://[AUTHGEAR_ENDPOINT]/saml2/metadata/[CLIENT_ID]

  • If the SP does not support uploading an IDP metadata file, you can manually enter the parameters into the SP. These values can be copied from the application settings page:

    • Issuer: urn:[AUTHGEAT_ENDPOINT]

    • Login URL: https://[AUTHGEAR_ENDPOINT]/saml2/login/[CLIENT_ID]

    • Logout URL: https://[AUTHGEAR_ENDPOINT]/saml2/logout/[CLIENT_ID]

    • Identity Provider Certificates in PEM format: Download from the application settings page

Configuration on Authgear

  • Upload the Metadata XML file provided by your client application into the Authgear Portal

  • You may also manually enter the parameters into the application settings page in the Portal:

    • NameID Format

      • urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified , or

        • When the format is unspecified, you can choose to use the User ID, Email, Phone, or Username as the attribute value

      • urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

    • Allowed Assertion Consumer Service URLs (ACS URLs)

    • Response Destination (Optional)

    • Subject Recipient (Optional)

    • Assertion Audience (Optional)

    • Assertion Valid Duration (seconds), Default: 1200

    • Enable/Disable Single Logout (SLO)

      • SLO Callback URL

      • Callback Binding

        • urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect, or

        • urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST

    • Enable/Disable message signature verification

      • Upload the SP's certificate in PEM format

You may find more detailed guides for adding IdP on the Service Provider's documentation.

Use Authgear as SAML Identity Provider for Dropbox

Guide on how to use Authgear as a SAML IdP for Dropbox

Use Authgear as SAML Identity Provider for Dropbox

Security Assertion Markup Language (SAML) is a standard that allows an Identity Provider (IdP) and a Service Provider (SP) to perform user authentication and authorization without exchanging a user's password.

In this post, you'll learn how to set up Authgear as an Identity Provider and Dropbox as a Service Provider.

Pre-requisites

  • An Authgear account. Sign up for free.

  • A Dropbox Business Advanced account.

Step 1: Create an Authgear Client Application

You need an Authgear client application of type OIDC/SAML Client Application to use Authgear as a SAML identity provider.

To create a new client application, log in to Authgear Portal, select your project then click on the Applications link from the navigation menu.

Next, click on Add Application to create a new client application. Alternatively, select an existing application of type OIDC/SAML Client Application and skip to step 2.

On the New Application page, enter Name and select OIDC/SAML Client Application as the Application Type.

Click Save to proceed.

Step 2: Enable SAML 2.0 in Client Application

By default, SAML 2.0 is not enabled for the client application.

To enable SAML for your client application, click on the SAML 2.0 tab then toggle the SAML 2.0 Support switch on.

Next, change NameID Format to urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress.

Add the following URL (Dropbox post-back URL) in Allowed Assertion Consumer Service URLs (ACS URLs) field:

https://www.dropbox.com/saml_login

Click on Save to keep your changes.

Step 3: Get SAML IdP Configuration and Download Certificate

Scroll down to the Configuration Parameters section of your Authgear client application's SAML 2.0 tab. Note the value for the login URL.

Also, download the Identity Provider Certificate for the client application to your computer.

You'll use the Login URL and certificate later in the Dropbox Admin console.

Step 4: Add Authgear SAML IdP in Dropbox

Log in to your Dropbox Business Advanced account then click on Admin console in the navigation menu.

In the Dropbox Admin console navigate to Settings > Single sign-on.

Now in the Dropbox Single sign-on settings page, set Single sign-on to Required. Then, configure the following:

  • Paste the value for your Authgear client application's Login URL in the Identity provider sign-in URL field.

  • Under X.509 certificate, click on the Certificate upload button, then upload the Identity Provider Certificate you downloaded from your Authgear client application in the previous step.

Step 5: Login to Dropbox Using Authgear SAML

To test your SAML implementation, you need to add a new user to your Dropbox with an email address that is associated with a user account in your Authgear project.

To add a new user to your Dropbox, navigate to Admin console > People > Members > Invite member.

Accept the invite for the new user, and try to log in to Dropbox using the registered email address for the new user. You should be redirected to the Authgear SAML login page. On successful login to the Authgear account, you should be redirected and signed in to Dropbox.

Use Authgear as SAML Identity Provider for Salesforce

A guide on how to use Authgear as a SAML Identity Provider IdP in Salesforce

The Service Provider (SP) trust the Identity Provider to handle the process of user authentication. The Identity Provider handles user authentication and notifies the Service Provider once the user is authenticated.

In this guide, you'll learn how to set up SAML with Authgear as an Identity Provider (IdP) and Salesforce as the Service Provider (SP) in SAML.

Pre-requisites

  • A Salesforce account.

Step 1: Create an Authgear Client Application

An Authgear Client application is required to set up Authgear as a SAML Identity Provider. To create an Authgear application, login to the Authgear Portal and navigate to the Applications in your project.

Click on Add Application to create a new application. Or, select an existing application that is of type OIDC/SAML Client Application and skip to step 2.

Now on the New Application page, enter a name for your application (e.g. My App) and set the Application Type to "OIDC/SAML Client Application".

Click Save to continue.

If prompted to view a tutorial, click Next to proceed to the application configuration page.

Step 2: Enable SAML 2.0 in Client Application

On the configuration page of your Authgear client application, switch to the SAML 2.0 tab. Toggle the SAML 2.0 Support switch on to enable SAML for the application.

Next, change NameID Format to urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress.

Enter your Salesforce domain in the Allowed Assertion Consumer Service URLs (ACS URLs) field under SSO Settings. You can get value for your Salesforce domain from the My Domain page on the Salesforce Setup page.

Click on Save to keep your changes.

Step 3: Get SAML Identity Provider (IdP) Configuration and Download Certificate

Still, on the SAML 2.0 tab, scroll to the Configuration Parameters section and click on the Download Metadata button to download the Identity Provider Metadata XML file for your Authgear application to your computer.

Next, scroll to the Identity Provider Certificates section and click Download Certificate to download the certificate to your computer.

You will use the downloaded metadata file and certificate in later steps.

Step 4: Enable SAML in Salesforce

To enable SAML in Salesforce, login to your Salesforce account, click on the Settings icon on the top right corner then select Setup. This will open the Salesforce Setup page.

On the Setup page, type "single sign-on" in the Quick find search box on the left. Select Single Sign-On from the result to open the Single Sign-On Settings page.

Next, click on the Edit button under Select Single Sign-On Settings then check the SAML Enabled box under Federated Single Sign-On Using SAML. Click Save to keep your changes.

Step 5: Add Authgear as SAML IdP in Salesforce

To add Authgear as a SAML Identity Provider, return to the main page of Single Sign-On Settings.

On the next screen, you should see configurations for your new SAML IdP, including the details from the metadata file. Edit the Name field to Authgear SAML. The value for the Name field will be visible on your Salesforce login page.

Once you're done with the above configurations, click Save to finish.

Step 6: Enable Login with SAML in Salesforce

In order to log in with a specific SAML IdP, you must first enable the provider in Salesforce.

To enable your new SAML IdP (Authgear SAML) search for "my domain" in Quick find. Click on My Domain from the result. On the My Domain page, scroll to Authentication Configuration then click on the Edit button.

You should find your Authgear SAMP IdP under Authentication Service. Check the box next to Authgear SAML to enable it. Click Save to keep changes.

Once you have enabled your SAML Identity provider in this step, it will be visible on your Salesforce login page the next time you attempt login.

Step 7: Log in to Salesforce using Authgear SAML

Force you can log in to your Salesforce project using Authgear SAML, you need to create a user using an email address that is linked to a user account in your Authgear project.

To create a user in Salesforce, use type "users" in the Quick find search box, then select Users > Users from the result. This will take you to the All Users page.

From the All Users page, click on New User. Create a new user with an email address that's linked to an account on your Authgear project.

Now, to test your SAML implementation, log out of Salesforce and attempt logging in again. This time, you should see a Login with Authgear SAML button.

When you click on Login with Authgear SAML, you should be redirected to Authgear Login page. Login to the account on your Authgear project that has the same email address as the new user you created earlier in this step. You should be successfully logged in to your Salesforce project.

SSO between Websites with the same apex domain

Requires all of the websites with the same "root domain" (e.g. app1.example.com and app2.example.com)

SSO between Mobile Apps and Browsers

Requires the use of ASWebAuthentication and Custom Tab on iOS/Android respectively

SSO between two independent mobile apps

Based on OIDC App2App

SSO from a Mobile App to Website

Open a URL from Mobile App and pass the user session along, based on OIDC Token Exchange

SSO between Mobile Apps from the same publisher

Keychain Sharing / Android Account Manager ( if you need it)

Requires both apps published by the same publisher from App Store.

The prompt="login" parameter which is defined in the can force AuthUI to show the login page. Authgear SDKs have a prompt parameter that can be used to set prompt="login". Once the prompt parameter is set to login Authgear will always show the login screen when your application calls the SDK's authenticate method.

Security Assertion Markup Language or short is a standard for exchanging security information between businesses. In SAML, one party acts as the Identity Provider (IdP), and the other party is the Service Provider (SP).

Security Assertion Markup Language or short is a standard for exchanging security information between businesses. In SAML, one party acts as the Identity Provider (IdP) and the other party is the Service Provider (SP).

An Authgear account. for free.

Next, click on the New from Metadata File button. Then, click Choose file, and select the Metadata XML file you downloaded in . Click on Create to continue.

Next, click on the Choose file button next to Identity Provider Certificate then select the SAML IdP Certificate file you downloaded in from your computer.

Cookie-based Deployment
SSO with Mobile App / Web SPA
App2App Login
Pre-Authenticated URLs
Contact us
Apple
Google
Facebook
GitHub
Linkedin
Azure Active Directory
Azure AD B2C
Microsoft AD FS
WeChat
Connect Apps to Apple
Connect Apps to Google
Connect Apps to GitHub
Connect Apps to LinkedIn
Connect Apps to WeChat
OIDC spec
SAML
SAML
Sign up
Step 3
Step 3

Connect Apps to Facebook

Add Facebook Sign in to your apps in less than 5 minutes.

This guide shows how to connect your Authgear application to Facebook so users can log in using the Login with Facebook feature.

Step 1: Create an App in Facebook for Developers

If you are using Authgear in your existing Facebook Apps, you may skip to the next step to set up the OAuth client.

Prerequisite

Create an App

On the next screen, select Other as your app use case then, click Next.

In the app type selection screen, pick the option that best meets your requirements. For our example, we'll select the Consumer app type.

Enter your app name on the next screen and finish the app creation process.

Step 2: Set up the OAuth Client

  1. In the app panel, click Add Product next to Products in the sidebar.

  2. Click the Set Up button in Facebook Login.

  3. Go to Settings of Facebook Login.

  4. Make sure Client OAuth Login and Web OAuth Login are enabled.

  5. Add https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/facebook to Valid OAuth Redirect URIs and save the changes.

Redirect URI has the form of https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/:alias. The alias is used as the identifier of OAuth provider. You can configure the alias in Authgear Portal.

Step 3: Configure Login with Facebook in Authgear Portal

Get your OAuth Client details

After setting up the Facebook Login product, go to App settings > Basic in the sidebar.

You will need the App ID and App Secret to configure Facebook Login so, note them down.

Configure in Authgear Portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Login with Facebook.

  3. Fill in the Client ID with the App ID obtained from the Facebook Developers portal in the previous step.

  4. Save the settings.

🎉 Done! You have just added Facebook Login to your apps!

Connect Apps to Google

Add Google Sign in to your apps in less than 5 minutes.

Set up OAuth client on Google Cloud Platform

To configure Google OAuth client for Authgear, you will need to create an OAuth client on Google Cloud Platform first.

Create a new project

Create OAuth Consent Screen

Create OAuth client ID

  1. Click Create Credentials -> OAuth client ID

  2. Choose Web application in Application type and assign a name as reference. You should always choose Web application here regardless of the platform of the app you are creating. It is because this OAuth Client ID is used by your Authgear services, which is a web application in Google’s classification.

  3. Add https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/google to redirect URIs.

  4. After creating a client ID, you will see the client ID under the OAuth 2.0 Client IDs section of the Credentials page.

Redirect URI has the form of /sso/oauth2/callback/:alias. The alias is used as the identifier of OAuth provider. You can configure the alias in Authgear Portal.

Configure Sign in with Google in Authgear Portal

Get your OAuth Client details

After creating an OAuth client, click the name of OAuth client to view the details.

You will need the values of Client ID, Client secret to configure Google Sign In.

Configure in Authgear Portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with Google.

  3. Fill in the Client ID and Client Secret with the values obtained from the previous step.

  4. Save the settings.

🎉Done! You have just added Google Sign In to your apps!

Connect Apps to LinkedIn

Prerequisite

  1. In the "Products" section, choose "Sign In with LinkedIn"

  2. In the details page of the created app, click the "Auth" tab

  3. Take notes of "Client ID" and "Client Secret", add https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/linkedin to "Redirect URLs" in "OAuth 2.0 settings" section

Redirect URI has the form of /sso/oauth2/callback/:alias. The alias is used as the identifier of OAuth provider. You can configure the alias in Authgear Portal

Configure Sign in with LinkedIn through the portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with LinkedIn.

  3. Fill in Client ID.

  4. Fill in Client Secret.

  5. Save the settings.

🎉 Done! You have just added Linkedin Login to your apps!

Connect Apps to Apple

Prerequisite

To configure "Sign in with Apple" for Authgear, you will need to fulfil the following:

  1. Register an Apple Developer Account. Apple Enterprise Account does not support "Sign in with Apple"

  2. Register your own domain.

  3. Your domain must be able to send and receive emails.

  4. Click "Configure" the Next to "Sign in with Apple". In "Primary App ID" field, select app ID created above.

  5. Fill in and verify the domain created above, add https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/apple to Return URLs

Redirect URI has the form of /sso/oauth2/callback/:alias. The alias is used as the identifier of OAuth provider. You can configure the alias in Authgear Portal.

Configure Sign in with Apple in Authgear Portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with Apple.

  3. Fill in the Client ID with the Service ID obtained above.

  4. In Apple Developer Portal, view key information of the "Key" created above.

  5. Jot down the Key ID and download the key text file (.p8 file).

  6. Copy the content in the key text file to Client Secret text area in Authgear Portal..

  7. Fill in Key ID field using the Key ID obtained from step 5.

  8. In Apple Developer Portal, click username on the top right corner, click View Membership.

  9. Find the Team ID from Membership Information, fill in Team ID field in Authgear portal.

  10. Save the settings.

🎉Done! You have just added Sign in with Apple to your apps!

Connect Apps to GitHub

Prerequisite

  1. In "Authorization callback URL", use https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/github.

  2. After the creation, click "Generate a new client secret". Remember the client secret.

Configure Sign in with GitHub through the portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with GitHub.

  3. Fill in Client ID.

  4. Fill in Client Secret.

  5. Save the changes.

🎉 Done! You have just added GitHub integration to your apps!

You will need a Facebook developer Account. Register as one by clicking Get Started in the website.

To create a new app, go to the Facebook Developers panel then click the Click Create App button.

See for instructions on how to get the value for YOUR_AUTHGEAR_ENDPOINT.

Your end-users can now sign in with Facebook on Authgear's pre-built Log In and Sign Up page. Existing end-users can connect their account to Facebook in the page.

Create a project on Google Cloud Platform through . If you are adding Authgear to your existing Google Cloud Platform projects, you may skip to the next step to create the OAuth client.

After creating a new project, you will need to configure the OAuth consent screen. Press the button on the top-left and go to APIs & Services -> OAuth consent screen and follow the instruction to create the consent screen.

Go to -> APIs & services -> Credentials

You can find more details in

Your end-users can now sign in with Google on Authgear pre-built Log In and Sign Up page. Existing end-users can connect their account to Google in the page.

Create an app in the .

Set up (SPF) for your domain.

Set up (DKIM) for your domain.

Create an "App ID" by adding a new "Identifier" , choose app IDs, enable "Sign in with Apple" enabled.

Create a "Services ID" by adding a new "Identifier" , choose service IDs, enable "Sign in with Apple".

Create a "Key" following with "Sign in with Apple" enabled. Click "Configure" next to "Sign in with Apple" and select "Primary App ID" with app ID created above. Keep the private key safe, you need to provide this later.

Follow the to create a OAuth App.

Facebook for Developers
Apps
User Settings
console
official Google Cloud Platform doc
User Settings
Linkedin Developers Portal
Sender Policy Framework
DomainKeys Identified Mail
here
here
this guide
official guide

Connect Apps to Microsoft AD FS

Prerequisite

  1. Setup your own AD FS server

  2. Create an application in your AD FS Server, obtain "Client ID", "Client Secret" and "Discovery Document Endpoint". Discovery Document Endpoint typically ends with /.well-known/openid-configuration. Configure your application with redirect uri https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/adfs.

Redirect URI has the form of /sso/oauth2/callback/:alias. The alias is used as the identifier of OAuth provider. You can configure the alias in Authgear Portal.

Configure Sign in with Microsoft AD FS through the portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with Microsoft AD FS.

  3. Fill in Client ID, Client Secret and Discovery Document Endpoint.

  4. Save the settings.

🎉 Done! You have just added Microsoft AD FS Login to your apps!

Force Users to Re-authenticate

Enterprise Login Providers

Guides on how to integrate identity providers to Authgear

Connect Apps to Azure Active Directory

Prerequisite

  1. Choose "Supported account type", the following options are supported:

    • Accounts in this organizational directory only (Contoso AD (dev) only - Single tenant)

    • Accounts in this organizational directory (Any Azure AD directory - Multitenant)

    • Accounts in this organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)

    "Personal Microsoft accounts only" is not supported yet. Remember the account type chosen as this affects the configuration on Authgear portal

  2. Configure "Redirect URI" with https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/azureadv2

Redirect URI has the form of /sso/oauth2/callback/:alias. The alias is used as the identifier of OAuth provider. You can configure the alias in Authgear Portal.

Configure Sign in with Microsoft through the portal

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with Microsoft

  3. Fill in Client ID with Application (client) ID of your just created Azure AD application.

  4. Fill in Client Secret" with the secret you get after creating a client secret for your Azure AD application.

  5. For Tenant field:

    • If single tenant (first option) is chosen, fill in the Directory (tenant) ID of your Azure AD application.

    • If multi tenant (second option) is chosen, fill in the string literal organizations.

    • If multi tenant and personal account (third option) is chosen, fill in the string literal common.

  6. Save the settings.

🎉 Done! You have just added Azure Active Directory (Azure AD) Login to your apps!

Force Login page

Connect Apps to Azure AD B2C

Prerequisite

  1. Configure "Redirect URI" with https://<YOUR_AUTHGEAR_ENDPOINT>/sso/oauth2/callback/azureadb2c.

  2. After creating the user flow, configure it

  • Open "Application Claims".

  • Make sure "Email Addresses" is checked.

Configure Sign in with Azure AD B2c through the portal

If you have finished the above prerequisite, you should have the following information:

  1. The Tenant Name, obtained in Step 2

  2. The Application (Client) ID, obtained in Step 5

  3. The Policy (User flow) Name, obtained in Step 7

Then in Authgear portal, do the following:

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with Microsoft Azure AD B2C.

  3. Fill in Client ID with the Application (Client) ID above.

  4. Fill in Client secret with the client secret you get when you create the app registration.

  5. Fill in Tenant with the Azure AD B2C Tenant Name.

  6. Fill in Policy with the Policy (User Flow) Name. Normally it starts with b2c_.

  7. Save the changes

🎉 Done! You have just added Azure AD B2C Login to your apps!

Force Login page

Force Social/Enterprise Login Providers to Show Login Screen

Use OIDC prompt parameter to force OAuth providers to show login screen.

In this post, you'll learn how to use prompt: "login" in Authgear SDKs to force OIDC providers to always show your users their login screen. You can also use prompt: "login" to allow users to switch accounts with a Social/Enterprise Login provider on the same device (or browser).

How to Force Social/Enterprise Login Providers to Show Login Page

Authgear SDKs have a prompt parameter that you can set in your application. The value of the prompt parameter will be passed to the Social/Enterprise Login provider. Hence, if you set prompt: "login" in the SDK, your Social/Enterprise Login provider will receive a prompt="login" parameter. The following code examples show how to use the prompt parameter in Authgear SDKs.

authgear
  .startAuthentication({
    redirectURI: "<AUTHGEAR_REDIRECT_URI>",
    prompt: PromptOption.Login,
  })
authgear
  .authenticate({
    redirectURI: 'com.reactnativeauth://host/path',
    prompt: PromptOption.Login,
  })
AuthenticateOptions options = new AuthenticateOptions("<AUTHGEAR_REDIRECT_URI>");
List<PromptOption> promptOptions = Arrays.asList(PromptOption.LOGIN);
options.setPrompt(promptOptions);
mAuthgear.authenticate(options, new OnAuthenticateListener() {
    @Override
    public void onAuthenticated(@Nullable UserInfo userInfo) {
        
    }

    @Override
    public void onAuthenticationFailed(@NonNull Throwable throwable) {
        Log.d(TAG, throwable.toString());
    }
});
authgear?.authenticate(
    redirectURI: "<AUTHGEAR_REDIRECT_URI>",
    prompt: "login"
)
_authgear.authenticate(
        redirectURI: "<AUTHGEAR_REDIRECT_URI>",
        prompt: "login",
      );

Connect Apps to WeChat

Web

Prerequisite

To create a website application in WeChat, you can choose to setup a website application and wait for approval or a sandbox account for testing.

Setup the Website Application (网站应用)

  • Create Website Application (网站应用), fill in information and wait for approval (It may take few days).

  • View the application detail page, obtain the "AppID" and "AppSecret" on the top of the application page.

  • Go to Account Center > Basic information, to obtain the "原始ID".

Setup the Sandbox Application (微信公众平台接口测试帐号)

  • Obtain the "appID", "appSecret" and "原始ID". The "原始ID" is the "微信号" in the top right corner.

  • Fill in 接口配置信息. The URL must be pointing at a publicly reachable server. The token is a string of your choice.

  • Implement the 接口配置信息 server. Here is an example written in Golang.

package main

import (
    "crypto/sha1"
    "crypto/subtle"
    "encoding/hex"
    "fmt"
    "io"
    "net/http"
    "sort"
    "strings"
)

type WechatVerifyHandler struct {
    Token string
}

func (h *WechatVerifyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    err := r.ParseForm()
    if err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    signature := r.Form.Get("signature")
    timestamp := r.Form.Get("timestamp")
    nonce := r.Form.Get("nonce")
    echostr := r.Form.Get("echostr")

    token := h.Token

    tmpArr := []string{token, timestamp, nonce}
    sort.Strings(tmpArr)

    tmpStr := strings.Join(tmpArr, "")

    hasher := sha1.New()
    io.WriteString(hasher, tmpStr)
    computedHash := hasher.Sum(nil)
    computedhashInHex := hex.EncodeToString(computedHash)

    if subtle.ConstantTimeCompare([]byte(signature), []byte(computedhashInHex)) == 1 {
        w.Write([]byte(echostr))
        return
    }

    http.Error(w, fmt.Sprintf("%v != %v", signature, computedhashInHex), http.StatusBadRequest)
}

func main() {
    http.Handle("/", &WechatVerifyHandler{
        Token: "TOKEN", // Change this value to the value you told Wechat!
    })
    http.ListenAndServe(":9999", nil)
}
  • Fill in JS接口安全域名. The value is your Authgear domain name plus port, e.g. 192.168.2.88:3000 or myapp.authgear.cloud

  • Fill in 网页授权获取用户基本信息. The value is your Authgear domain name plus port, e.g. 192.168.2.88:3000 or myapp.authgear.cloud

  • Look for an QR code in the sandbox settings page. You must scan it with your Wechat app and follow the sandbox account.

Configure Sign in with WeChat through the Authgear portal

In the portal, do the following:

  1. In the portal, go to Authentication > Social / Enterprise Login.

  2. Enable Sign in with WeChat (Web/网站应用).

  3. Fill in Client ID with the AppID.

  4. Fill in Client Secret with the AppSecret.

  5. Fill in 原始 ID with the 原始 ID.

  6. Check the checkbox Is Sandbox account if you are using sandbox account.

  7. Save the settings.

Mobile app (Native iOS app, Native Android app, React Native, and Flutter)

Overview of Setting Up Wechat

Wechat integration is a bit more complicated then other social login, here are the overview of what needs to be done:

  • Register an account and create mobile application in WeChat Open Platform. Approval is needed in this process.

  • Enable and configure WeChat Login in Authgear portal.

  • Include Authgear SDK on your app.

  • Implement a delegate function to be triggered when user clicks the "Login with WeChat" button during authorization. You need to integrate WeChat SDK to open WeChat app to perform authentication in the delegate function (we have sample code below). After obtaining the authorization code from WeChat, call the Authgear callback with the auth code and complete the "Login With WeChat" process.

Here are the detailed steps for iOS, Android, React Native, and Flutter.

Prerequisite - Setup the Mobile Application (移动应用)

  • Create Mobile Application (移动应用), fill in information and wait for approval (It may take few days).

  • View the application detail page, obtain the AppID and AppSecret on the top of the page.

  • Go to Account Center > Basic information, to obtain the "原始ID".

  • Save those values, we will need them in the section below.

Update code based on platform

Native iOS application

  • Setup Authgear iOS SDK.

  •   #ifndef WechatOpenSDK_Bridging_Header_h
      #define WechatOpenSDK_Bridging_Header_h
    
      #import "WXApiObject.h"
      #import "WXApi.h"
    
      #endif
  • After setting up the WechatOpenSDK, universal link should be enabled in your application. We will need two links for the setup. One is for the WeChat SDK used, another is for the Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here are the suggestion of the links.

    • WECHAT_UNIVERICAL_LINK: https://{YOUR_DOMAIN}/wechat

    • WECHAT_REDIRECT_URI_FOR_AUTHGEAR: https://{YOUR_DOMAIN}/open_wechat_app

  • Login WeChat Open platform, open the application detail page, update the development information iOS section.

  • Fill in "Bundle ID" field with your app bundle id.

  • Fill in "Universal Links" with "WECHAT_UNIVERICAL_LINK" above.

  • Go to Authgear portal, do the following:

    • In the portal, go to Authentication > Social / Enterprise Login.

    • Enable Sign in with WeChat (Mobile/移动应用).

    • Fill in Client ID with the AppID.

    • Fill in Client Secret with the AppSecret.

    • Fill in 原始 ID with the 原始 ID.

    • Add WECHAT_REDIRECT_URI_FOR_AUTHGEAR above in WeChat redirect URIs.

    • Save the settings.

  • Update the code

    • Setup WeChat SDK when app launch

        // Replace WECHAT_APP_ID with wechat app id
        // Replace WECHAT_UNIVERICAL_LINK with the link defined above
        WXApi.registerApp("WECHAT_APP_ID", universalLink: "WECHAT_UNIVERICAL_LINK")
        WXApi.startLog(by: .detail) { log in
            print(#line, "wechat sdk wxapi: " + log)
        }
    • Setup Authgear delegate and call WeChat SDK when sendWechatAuthRequest is triggered

        // Replace self with the object that you implement the AuthgearDelegate
        authgear.delegate = self
      
        // Replace WECHAT_APP_ID with wechat app id
        extension MyClass: AuthgearDelegate {
            func sendWechatAuthRequest(_ state: String) {
                let req = SendAuthReq()
                req.openID = "WECHAT_APP_ID"
                req.scope = "snsapi_userinfo"
                req.state = state
                WXApi.send(req)
            }
        }
    • Handle universal link

        // Update App Delegate
        func application(_ application: NSApplication,
                        continue userActivity: NSUserActivity,
                        restorationHandler: @escaping ([NSUserActivityRestoring]) -> Void) -> Bool {
            // wechat sdk handle, replace self with object implement WXApiDelegate
            WXApi.handleOpenUniversalLink(userActivity, delegate: self)
            // authgear sdk handle
            return authgear.application(application, continue: userActivity, restorationHandler: restorationHandler)
        }
      
        // If your app has opted into Scenes, Update Scene Delegate
        func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
            // wechat sdk handle, replace self with object implement WXApiDelegate
            WXApi.handleOpenUniversalLink(userActivity, delegate: self)
      
            // authgear sdk handle
            authgear.scene(scene, continue: userActivity)
        }
      
        // Implement WXApiDelegate
        extension MyClass: WXApiDelegate {
            func onReq(_ req: BaseReq) {}
            func onResp(_ resp: BaseResp) {
                // Receive code from WeChat, send callback to authgear
                // by calling `authgear.wechatAuthCallback`
                if resp.isKind(of: SendAuthResp.self) {
                    if resp.errCode == 0 {
                        let _resp = resp as! SendAuthResp
                        if let code = _resp.code, let state = _resp.state {
                            authgear.wechatAuthCallback(code: code, state: state) { result in
                                switch result {
                                case .success():
                                    // send wechat auth callback to authgear successfully
                                case let .failure(error):
                                    // failed to send wechat auth callback to authgear
                                }
                            }
                        }
                    } else {
                        // failed to obtain code from wechat sdk
                    }
                }
            }
        }
    • Provide wechatRedirectURI when calling authenticate and promoteAnonymousUser in authgear sdk

        // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
        container?.authenticate(
            redirectURI: "REDIRECT_URI",
            prompt: "login",
            wechatRedirectURI: "WECHAT_REDIRECT_URI_FOR_AUTHGEAR"
        ) { result in
        }
      
        // For anonymous user support only
        // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
        container?.promoteAnonymousUser(
            redirectURI: "REDIRECT_URI",
            wechatRedirectURI: "WECHAT_REDIRECT_URI_FOR_AUTHGEAR"
        ) { result in
        }
      
        // Open setting page
        // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
        container?.open(
            page: .settings,
            wechatRedirectURI: "WECHAT_REDIRECT_URI_FOR_AUTHGEAR"
        )

Native Android application

  • Setup Authgear iOS SDK.

  • Login WeChat Open platform, open the application detail page, update the development information Android section.

  • Fill in application signature, you can obtain it with command keytool -list -v -keystore YOUR_KEYSTORE_FILE_PATH. WeChat needs the certificate fingerprint in MD5, remove : in the fingerprint. It should be string in length 32.

  • Fill in your package name

  • We will need to define a custom url for Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here is the example, you should update it with your own scheme.

    • "WECHAT_REDIRECT_URI_FOR_AUTHGEAR": com.myapp://host/open_wechat_app

  • Go to Authgear portal, do the following:

    • In the portal, go to Authentication > Social / Enterprise Login.

    • Enable Sign in with WeChat (Mobile/移动应用).

    • Fill in Client ID with the AppID.

    • Fill in Client Secret with the AppSecret.

    • Fill in 原始 ID with the 原始 ID.

    • Add WECHAT_REDIRECT_URI_FOR_AUTHGEAR above in WeChat redirect URIs.

    • Save the settings.

  • Update the code

    • Update application AndroidManifest.xml

        <!-- Your application configuration. Omitted here for brevity -->
        <application>
        <!-- Other activities or entries -->
      
        <!-- It should be added when setting up Authgear SDK -->
        <activity android:name="com.oursky.authgear.OauthRedirectActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- This is the redirectURI, It should be added when setting up Authgear SDK -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/path"/>
                <!-- Add this for WeChat setup, this should match the WECHAT_REDIRECT_URI_FOR_AUTHGEAR defined above -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/open_wechat_app"/>
            </intent-filter>
        </activity>
      
        <!-- Add this for WeChat SDK setup, replace YOUR_PACKAGE_NAME-->
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:taskAffinity="YOUR_PACKAGE_NAME"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
        </application>
    • Configure WeChat SDK

        private IWXAPI wechatAPI;
      
        private setupWechatSDK() {
            wechatAPI = WXAPIFactory.createWXAPI(app, YOUR_WECHAT_APP_ID, true);
            wechatAPI.registerApp(YOUR_WECHAT_APP_ID);
        }
    • Setup Authgear delegate

        mAuthgear.setDelegate(new AuthgearDelegate() {
            @Override
            public void sendWechatAuthRequest(String state) {
                if (!wechatAPI.isWXAppInstalled()) {
                    // User have not installed WeChat app, show them the error
                    return;
                }
                SendAuth.Req req = new SendAuth.Req();
                req.scope = "snsapi_userinfo";
                req.state = state;
                wechatAPI.sendReq(req);
            }
        });
    • Create wxapi directory in the directory named after your package name and create WXEntryActivity activity. In WXEntryActivity, pass the received intent and the object that implements IWXAPIEventHandler API to the handleIntent method of the IWXAPI API, as shown below:

        api.handleIntent(getIntent(), this);

      You will be able to receive the authentication code and state in onResp method, call Authgear wechatAuthCallback with code and state.

        mAuthgear.wechatAuthCallback(code, state, new OnWechatAuthCallbackListener() {
            @Override
            public void onWechatAuthCallback() {
            }
      
            @Override
            public void onWechatAuthCallbackFailed(Throwable throwable) {
            }
        });
    • Provide wechatRedirectURI when calling authorize and promoteAnonymousUser in Authgear SDK.

        // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
        AuthenticateOptions options = new AuthenticateOptions(AUTHGEAR_REDIRECT_URI);
        options.setWechatRedirectURI(WECHAT_REDIRECT_URI_FOR_AUTHGEAR);
        mAuthgear.authenticate(options, new OnAuthenticateListener() {
            @Override
            public void onAuthenticated(@Nullable UserInfo userInfo) {
            }
      
            @Override
            public void onAuthenticationFailed(@NonNull Throwable throwable) {
            }
        });
      
        // For anonymous user support only
        // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
        PromoteOptions options = new PromoteOptions(AUTHGEAR_REDIRECT_URI);
        options.setWechatRedirectURI(WECHAT_REDIRECT_URI_FOR_AUTHGEAR);
        mAuthgear.promoteAnonymousUser(options, new OnPromoteAnonymousUserListener() {
            @Override
            public void onPromoted(@NonNull UserInfo userInfo) {
            }
      
            @Override
            public void onPromotionFailed(@NonNull Throwable throwable) {
            }
        });
      
        // Open setting page
        // Replace "WECHAT_REDIRECT_URI_FOR_AUTHGEAR" with link defined above
        SettingOptions options = new SettingOptions();
        options.setWechatRedirectURI(WECHAT_REDIRECT_URI_FOR_AUTHGEAR);
        mAuthgear.open(Page.Settings, options);

React Native

  • Setup Authgear SDK

  • In iOS, after setting up the WechatOpenSDK, universal link should be enabled in your application. We will need two links for the setup. One is for the WeChat SDK used, another is for the Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here are the suggestion of the links.

    • IOS_WECHAT_UNIVERSAL_LINK: https://{YOUR_DOMAIN}/wechat

    • IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR: https://{YOUR_DOMAIN}/open_wechat_app

  • In android, you need to sign your app to use WeChat SDK. Obtain your application signature by running command keytool -list -v -keystore YOUR_KEYSTORE_FILE_PATH with your keystore file. WeChat needs the certificate fingerprint in MD5, remove : in the fingerprint. It should be string in length 32.

  • Login WeChat Open platform, open the application detail page, update the development information iOS and Android sections.

  • In iOS

    • Fill in "Bundle ID" field with your app bundle id.

    • Fill in "Universal Links" with "IOS_WECHAT_UNIVERSAL_LINK" above.

  • In Android

    • Fill in application signature.

    • Fill in your package name

  • For android, we will need to define a custom url for Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here is the example, you should update it with your own scheme.

    • ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR: com.myapp://host/open_wechat_app

  • Login Authgear portal, go to "Single-Sign On" page, then do the following:

    • Enable "Sign in with WeChat (Mobile/移动应用)"

    • Fill in "Client ID" with the WeChat "AppID".

    • Fill in "Client Secret" with the WeChat "AppSecret".

    • Fill in "原始 ID" with the WeChat "原始 ID".

    • Add "IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR" and "ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR" above into "WeChat redirect URIs"

    • Click save.

  • Update the code

    • In Android, Update application AndroidManifest.xml.

        <!-- Your application configuration. Omitted here for brevity -->
        <application>
        <!-- Other activities or entries -->
      
        <!-- It should be added when setting up Authgear SDK -->
        <activity android:name="com.authgear.reactnative.OAuthRedirectActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- This is the redirectURI, It should be added when setting up Authgear SDK -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/path"/>
                <!-- Add this for WeChat setup, this should match the WECHAT_REDIRECT_URI_FOR_AUTHGEAR defined above -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/open_wechat_app"/>
            </intent-filter>
        </activity>
      
        <!-- Add this for WeChat SDK setup, replace YOUR_PACKAGE_NAME-->
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:taskAffinity="YOUR_PACKAGE_NAME"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
        </application>
    • In iOS, update your App Delegate

        - (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
            [WXApi handleOpenUniversalLink:userActivity delegate:self];
            [AGAuthgearReactNative application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
            return YES;
        }
    • Provide wechatRedirectURI when calling Authgear SDK authorize and promoteAnonymousUser in js

        // REPLACE IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR and ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR
        const wechatRedirectURI = Platform.select<string>({
            android: 'ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR',
            ios: 'IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR',
        });
      
        authgear
            .authenticate({
                redirectURI: "REDIRECT_URI",
                wechatRedirectURI: wechatRedirectURI
      
            });
      
        // For anonymous user support only
        authgear
            .promoteAnonymousUser({
                redirectURI: "REDIRECT_URI",
                wechatRedirectURI: wechatRedirectURI
            });
      
        // Open setting page
        authgear
            .open(Page.Settings, {
                wechatRedirectURI: wechatRedirectURI,
            })
    • Setup Authgear delegate and open WeChat SDK when sendWechatAuthRequest is triggered

        authgear.delegate = {
            sendWechatAuthRequest: (state) => {
                // User click login with WeChat
                // Implement native modules to use WeChat SDK to open 
                // WeChat app for authorization.
                // After obtaining authorization code, call Authgear.wechatAuthCallback
                // to complete the authorization.
                const {WechatAuth} = NativeModules;
                WechatAuth.sendWechatAuthRequest(state)
                .then((result: {code: string; state: string}) => {
                    // Native module sending back the code after login with
                    // WeChat app. Call Authgear.wechatAuthCallback
                    return authgear.wechatAuthCallback(result.code, result.state);
                })
                .then(() => {
                    // Send WeChat callback to authgear successfully
                })
                .catch((err: Error) => {
                    // error ocurred
                });
            }
        }

Flutter

  • Setup Authgear SDK

  • In iOS, after setting up the WechatOpenSDK, universal link should be enabled in your application. We will need two links for the setup. One is for the WeChat SDK used, another is for the Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here are the suggestion of the links.

    • IOS_WECHAT_UNIVERSAL_LINK: https://{YOUR_DOMAIN}/wechat

    • IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR: https://{YOUR_DOMAIN}/open_wechat_app

  • In android, you need to sign your app to use WeChat SDK. Obtain your application signature by running command keytool -list -v -keystore YOUR_KEYSTORE_FILE_PATH with your keystore file. WeChat needs the certificate fingerprint in MD5, remove : in the fingerprint. It should be string in length 32.

  • Login WeChat Open platform, open the application detail page, update the development information iOS and Android sections.

  • In iOS

    • Fill in "Bundle ID" field with your app bundle id.

    • Fill in "Universal Links" with "IOS_WECHAT_UNIVERSAL_LINK" above.

  • In Android

    • Fill in application signature.

    • Fill in your package name

  • For android, we will need to define a custom url for Authgear SDK to trigger delegate function when user click "Login with WeChat" button. Here is the example, you should update it with your own scheme.

    • ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR: com.myapp://host/open_wechat_app

  • Login Authgear portal, go to "Single-Sign On" page, then do the following:

    • Enable "Sign in with WeChat (Mobile/移动应用)"

    • Fill in "Client ID" with the WeChat "AppID".

    • Fill in "Client Secret" with the WeChat "AppSecret".

    • Fill in "原始 ID" with the WeChat "原始 ID".

    • Add "IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR" and "ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR" above into "WeChat redirect URIs"

    • Click save.

  • Update the code

    • In Android, Update application AndroidManifest.xml.

        <!-- Your application configuration. Omitted here for brevity -->
        <application>
        <!-- Other activities or entries -->
      
        <!-- It should be added when setting up Authgear SDK -->
        <activity android:name="com.authgear.flutter.OAuthRedirectActivity"
            android:exported="true"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <!-- This is the redirectURI, It should be added when setting up Authgear SDK -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/path"/>
                <!-- Add this for WeChat setup, this should match the WECHAT_REDIRECT_URI_FOR_AUTHGEAR defined above -->
                <data android:scheme="com.myapp"
                    android:host="host"
                    android:pathPrefix="/open_wechat_app"/>
            </intent-filter>
        </activity>
      
        <!-- Add this for WeChat SDK setup, replace YOUR_PACKAGE_NAME-->
        <activity
            android:name=".wxapi.WXEntryActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:taskAffinity="YOUR_PACKAGE_NAME"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"></activity>
        </application>
    • Provide wechatRedirectURI.

        // REPLACE IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR and ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR
        var wechatRedirectURI = "";
        if (Platform.isIOS) {
            wechatRedirectURI = 'IOS_WECHAT_REDIRECT_URI_FOR_AUTHGEAR';
        } else if (Platform.isAndroid) {
            wechatRedirectURI = 'ANDROID_WECHAT_REDIRECT_URI_FOR_AUTHGEAR';
        }
      
        await authgear.authenticate(redirectURI: "REDIRECT_URI", wechatRedirectURI: wechatRedirectURI);
      
        // For anonymous user support only
        await authgear.promoteAnonymousUser(redirectURI: "REDIRECT_URI", wechatRedirectURI: wechatRedirectURI);
      
        // Open setting page
        await authgear.open(SettingsPage.settings, wechatRedirectURI: wechatRedirectURI);
    • Provide sendWechatAuthRequest

      final authgear = Authgear(
          sendWechatAuthRequest: sendWechatAuthRequest,
      );
      
      Future<void> sendWechatAuthRequest(state: String) async {
          // Implement your platform specific code to use WeChat SDK to open WeChat app.
          // After success, pass the code back to Authgear.
          await authgear.wechatAuthCallback(state: state, code: code);
      }

Built-in UI

Authgear lets you customize your users’ entire authentication experience

Brand and customize login experience for your users where you can customize domain, email, and localize to handle different languages.

Your end-users can connect to their Facebook account in User Settings page
OAuth Client ID in the Credentials page
Get your OAuth Client ID and Secret in the details page
"Sign in with Google" in Log in and Sign up page
Your end-users can connect to their Google account in User Settings page

Microsoft AD FS supports the prompt=login parameter. You can include this parameter in your request when you want users to re-authenticate. See our in Authgear SDKs to learn more.

Create an Azure Active Directory (Azure AD) account

Setup a tenant by completing

Register an application by completing

Follow section to add a client secret. Remember to record the secret value when you add the client secret, as it will not be displayed again. This will be needed for configure OAuth client in Authgear.

Azure Active Directory automatically logs in to the same account without requiring a username and password. To prevent this behaviour, you can use the prompt=login parameter to force Azure Active Directory to show the login page. See our in Authgear SDKs to learn more.

Sign in .

Create a B2C tenant by following .

Enable self-service sign-up for the tenant by following

Go back the main page of and search for "Azure AD B2C"

Create a app registration for Authgear by following .

Follow to create a sign-up and sign-in user flow.

Azure AD B2C automatically logs in to the same account without requiring a username and password. To prevent this behaviour, you can use the prompt=login parameter to force Azure AD B2C to show the login page. See our in Authgear SDKs to learn more.

The prompt="login" parameter which is defined in the can prompt Social/Enterprise Login Providers to always show their login screen. As a result, you can use the prompt="login" parameter to allow users to switch accounts when their previous authentication session on the provider is still stored.

Register an account in .

Use your WeChat app to login in .

Register an account in .

Follow to setup WeChat SDK. For the coding part, we will further explain in the below steps.

WechatOpenSDK is Objective-C library. If you are using swift. You will need to create bridging header. To setup bridge header, please check . Here is the example WechatOpenSDK-Bridging-Header.h.

Here is the completed .

Follow to setup Wechat SDK. For the coding part, we will further explain in the below steps.

Here is the completed .

Follow and to setup WeChat SDK. For the coding part, we will further explain in the below steps.

Implement the NativeModules to use WeChat SDK to open WeChat app for authorization. Here is the completed .

Follow and to setup WeChat SDK. For the coding part, we will further explain in the below steps.

Implement the platform specific code to use WeChat SDK to open WeChat app for authorization. Here is the completed .

guide on using the prompt=login parameter
Connect Apps to Azure Active Directory
Connect Apps to Microsoft AD FS
Connect Apps to Azure AD B2C
here
Quickstart: Set up a tenant
Quickstart: Register an application with the Microsoft identity platform
this
guide on using the prompt=login parameter
Microsoft Azure
this tutorial
this doc
Microsoft Azure
this guide
this guide
guide on using the prompt=login parameter
OIDC spec
WeChat Open Platform
微信公众平台接口测试帐号申请
WeChat Open Platform
iOS接入指南
Importing Objective-C into Swift
example
Android接入指南
example
iOS接入指南
Android接入指南
example
iOS接入指南
Android接入指南
example

User Settings

Authgear provides a wide range of prebuilt frontend for the authentication related features of your apps

Actions in the settings page

The end-user can perform the following actions on the setting page:

  • Change their password.

  • Add or change their email, phone number or username.

  • Connect or disconnect to identity providers.

  • Manage the signed in sessions.

  • Enable or disable 2-step verification.

  • and many more.

Open the settings page in websites

Use the open method to open the built-in settings page

import authgear, { Page } from "@authgear/web";

const openSettings = () = {
    authgear.open(Page.Settings)
}

Open the settings page with the SDK in mobile apps

If you are working on a mobile apps, you can open the settings page using the SDK. When the end-user has signed in, the SDK provides a method to open the settings page in a webview.

import React, { useCallback } from "react";
import authgear, { Page } from "@authgear/react-native";
import { View, Button } from "react-native";

function SettingsScreen() {
  const onPressOpenSettingsPage = useCallback(() => {
    authgear.open(Page.Settings).then(() => {
      // When the promise resolves, the webview have been closed.
    });
  }, []);
  return (
    <View>
      <Button
        title="Open Settings Page"
        onPress={onPressOpenSettingsPage}
      />
    </View>
  );
}
Future<void> onPressOpenSettingsPage() async {
  await authgear.open(SettingsPage.settings);
}
async void OnOpenSettingsClicked(object sender, EventArgs args)
{
  await authgear.OpenAsync(SettingsPage.Settings);
}
func onPressOpenSettingsPage(sender: UIButton, forEvent event: UIEvent) {
    authgear.open(.settings) {
        // When the completion handler is called, the webview is closed.
    }
}
public void onClickOpenSettingsPage() {
    authgear.open(Page.Settings, null, new OnOpenURLListener() {
        @Override
        public void onClosed() {
            // The webview is closed.
        }

        @Override
        public void onFailed(Throwable throwable) {
            // Some error occurred.
        }
    });
}

Back to my app button

In web-based application, you may want to add the "Back to my app" button to the settings page so the user can navigate back to your website after changing the settings.

  1. Go to Portal > UI Settings

  2. Provide the URL in Back to Your App Link and click Save

Branding in Auth UI
User Settings
Privacy Policy & Terms of Service Links
Customer Support Link
Custom Text

Privacy Policy & Terms of Service Links

You can add a privacy policy and a terms of service link to the sign up page.

Change in the Portal

These two links can be easily added in the project Portal

  1. Go to UI Settings in the Portal

  2. Fill in the Privacy Policy Link and Terms of Service Link in the Link Settings section

  3. Save the settings.

The values will be used as the href of <a> HTML tag so they must be valid URL. If both of the links are left empty, the whole paragraph on the signup page will be hidden.

Edit translation.json

You can also add these links by including two special translation keys in translation.json.

The keys are terms-of-service-link and privacy-policy-link. The values will be used as the href of <a> HTML tag so they must be valid URL.

For example,

{
  "terms-of-service-link": "https://mycompany.com/terms-of-service",
  "privacy-policy-link": "https://mycompany.com/privacy-policy"
}

If you wish to hide the whole paragraph, set BOTH to empty string.

Customer Support Link

Let end-user to contact customer support in case they need help in the login process.

In the case of losing access to the MFA authenticators, the end-user can recover their account by using the emergency Recovery Codes. However they may have lost the codes and need customer support.

Set customer support link

You can add a customer support link in the Portal.

  1. Go to UI Settings in the Portal

  2. Fill in the Customer Support Link in the Link Settings section

  3. Save the settings.

The value will be used as the href of <a> HTML tag. It can be a URL or a mailto: link.

Customize the label

You can also modify the text shown to the end-users by including two special translation keys in translation.json.

{
    "enter-recovery-code-instead-v1": "Having Trouble? <button class=\"btn secondary-btn\" type=\"submit\">Use recovery code</button>",
    "enter-recovery-code-instead-with-customer-support-v1": "Having Trouble? <button class=\"btn secondary-btn\" type=\"submit\">Use recovery code</button> or <a class=\"link\" target=\"_blank\" href={customerSupportLink}>contact customer support</a>",
}

Custom Text

You can use your own translation or change the default text in the AuthUI. To do this, you'll edit translation.json.

Custom Text enables the customization of specific UI texts in AuthUI for different languages.

Follow these steps to change any text in AuthUI.

  1. Go to Portal > Branding > Custom Text

The value you add will override the default and if you remove a key-value pair, Authgear will use the default value.

Branding in Auth UI

Customize the look and feel of Authgear to match your branding

Authgear makes it easy for you to customize the built-in AuthUI to meet the specific branding needs of your application. You can customize UI elements such as the logo, text input fields, and buttons.

In this guide, you'll learn how to use all the customization options available.

Authgear Design Page

To open the new Authgear Design page, log in to the Authgear Portal and navigate to Branding > Design.

The Design page is divided into 2 columns. The left column shows a preview of your customizations in real time. The right column is the menu with all the customization options for different UI elements (e.g. Name, Logo, Favicon).

Customization Options

1. Name

Use this option to set the application name you want to display in AuthUI (Login and Register pages).

2. Theme

The Theme options allow you to switch between Light Mode, Dark Mode, or Auto (User Preference) on the Design page and for your project. If you select a theme and click the Save button, that theme will be applied to your project.

When the Auto based on user preference theme option is selected, AuthUI will choose a theme based on a specific user's settings.

3. Logo

The logo option allows you to replace the default Authgear logo in AuthUI with your own brand logo. You can add a PNG, JPG, or GIF image smaller than 100 KB.

4. Favicon

Use this option to add a custom favicon that will show in browser tabs. The size of the image you upload must be a multiple of 32px square, and be a PNG, JPG, or GIF file.

5. Card

The card option allows you to set the Alignment of the AuthUI card. By default, the AuthUI card is aligned to the Center. You change the alignment to either Left, Right, or Center.

6. Background

Use this option to change the background color of AuthUI pages. You can either use a background color (CSS hexadecimal color code) or upload a PNG, JPEG, or GIF image smaller than 1 MB.

7. Buttons

The button customization option lets you customize multiple properties of the buttons in AuthUI. The following are the properties you can customize:

Primary button: Use this field to set the fill color of the buttons.

Primary button label: Use this field to set the color of the text inside a button.

Border radius style: Set the type of border-radius you want here. Available options include square edges, curved edges, and full-rounded ends.

Border radius: The curved edges Border radius style allows further customization for the actual size of the border radius in pixels. Use this option to set the level of curved edges.

8. Links

Link color: Use this option to set the text color for links in AuthUI. The value should be a hexadecimal color code.

Link decoration: You can use this option to add the underline text-decoration to links that are displayed in AuthUI.

Privacy Policy: Use this option to add a link to your privacy policy page.

Terms of Service: Use this option to set a custom link for your terms of service

Customer Support: Use this option to add a link to your support page.

Note that when any of the link properties is unset AuthUI will fall back to the primary language's default settings.

9. Input field

The Input field section contains options for styling text input fields in AuthUI. The following are the various properties you can set:

Border radius style: Use this option to set the type of border-radius you want. The available options are square edges, curved edges, and full-rounded ends.

Border radius: You can use this option to further customize the level of curve of the curved edges Border radius style.

10. Back to your app

11. Authgear branding

You can use this toggle to remove Authgear branding in the AuthUI for your project.

Customize Dark Mode and Light Mode

Attributes of the default AuthUI dark mode and light mode can be customized. For example, you can change the default color of the dark background in dark mode.

To customize an attribute, select the theme (light or dark mode) you wish to customize, then navigate to the attribute you wish to customize and modify it. Or select Auto based on user preference to see customization options for both themes at the same time.

The following are attributes you can customize for each theme:

Contact customer support in the 2-step verification screen

Override translation by adding the key-value pair or modifying the value of an existing key in the JSON object in the text box. See default translation.json for a list of available keys and their default values.

The Language drop-down on the top right corner allows you to customize AuthUI text such as Organisation Name, and (Privacy Policy, Terms of Service, and Customer Support) for specific languages.

You can also use the Design page to select a theme (Dark mode or Light mode) to further customize it. Skip to the to learn more

Under the Links section, you'll find options to set the text color for links in AuthUI and also options for configuring , and that are linked on AuthUI.

Use this option to add a button under the to navigate the user to your website.

(fill color and label color)

here
Privacy Policy, Terms of Service
Customer Support
user settings page
links
Dark mode section
Logo
Background
Buttons
Link Color

Authentication Flow API

Learn about what the Authentication Flow API is and how to use it to implement your own custom user interface (UI) for authentication.

Build your own custom UI for login, signup, and more powered by the Authentication Flow API.

By default, when you set up an Authgear project, it makes use of the regular AuthUI offered by Authgear. Although AuthUI offers many customization options such as the ability to change the theme and color or add your brand logo to authentication pages, you might have more needs. With the Authentication Flow API, you can build your own authentication UI from the ground up, and using your preferred programming language and tool.

What is the Authentication Flow API?

The Authentication Flow API is an REST HTTP API that you can use to create and run an authentication flow. You can use this API to create your own custom UI for pages like login, signup, account recovery, 2FA, and more.

To use the API on its own you make an HTTP request to one of the valid endpoints as shown below:

Endpoint: {your-authgear-project-domain}/api/v1/authentication_flows

Request method: POST

Request header:

{
    "Content-Type": "application/json",
    "Accept": "application/json",
}

All requests to the API should include the above header.

Request body:

{
    "type": "login",
    "name": "default"
}

The following is a sample of the response you would get from the Authentication Flow API for the above request:

{
    "result": {
        "state_token": "authflowstate_VGHZ8SBCKGZK2KW84TCAKWGM8QZH0B69",
        "type": "login",
        "name": "default",
        "action": {
            "type": "identify",
            "data": {
                "options": [
                    {
                        "identification": "phone"
                    },
                    {
                        "identification": "email"
                    },
                    {
                        "identification": "oauth",
                        "provider_type": "google",
                        "alias": "google"
                    }
                ]
            }
        }
    }
}

The above response means you've successfully started a new login flow using the API.

To continue and finish the authentication flow, you can send the value for state_token from the above response in your next HTTP request to the api/v1/authentication_flows/states/input endpoint like the example shown below:

Endpoint: {your-authgear-project-domain}/api/v1/authentication_flows/states/input

Request method: POST

To help you understand the structure of the Authentication Flow API HTTP(S) request, here is an example of an actual request in Postman:

Request body:

{
    "state_token": "authflowstate_VGHZ8SBCKGZK2KW84TCAKWGM8QZH0B69",
    "input": {
        "identification": "email",
        "login_id": "user@example.com"
    }
}

In this second request (or second step of the authentication flow), we use the state_token from the response to the previous request in the request body to continue the authentication flow. The request body includes the input field that passes the type of identification the user will provide (for example, email) and the login_id which is the actual value for the user's identification.

The response to the above request should look like this:

{
    "result": {
        "state_token": "authflowstate_ABCJVB0IJKLQ2S1K2G34RX56R1C1E789",
        "type": "login",
        "name": "default",
        "action": {
            "type": "authenticate",
            "data": {
                "type": "authentication_data",
                "options": [
                    {
                        "authentication": "primary_password"
                    }
                ],
                "device_token_enabled": false
            }
        }
    }
}

You may send more requests just like this second request depending on the number of steps required for your specific authentication flow. For example, to complete the login authentication flow, send another request with the the authenticator (password) like this:

{
    "state_token": "authflowstate_ABCJVB0IJKLQ2S1K2G34RX56R1C1E789",
    "input": {
        "authentication": "primary_password",
        "password": "sup3r$tr0ngpa$$"
    }
}

To use the Authentication Flow API to build your custom UI, you need to configure a Custom UI URI in the Authgear portal. This URI should point to your custom authentication page.

How the Authentication Flow API Works

The following flowchart shows the steps in a simple Authentication Flow API implementation:

Step 1: Make Authorization Request

When you use the authentication flow API to power your custom UI, the authentication flow for your app will start with your app sending an authorization request to Authgear's authorization server as shown in step 1 in the figure above.

Step 2: Redirect to Custom UI

If you have Authentication Flow API enabled and a Custom UI URI set for your Authgear App, the authorization server will redirect your users to the custom UI as shown in step 2 above.

Step 3: Make HTTP Requests to Authentication Flow API Endpoints

In your custom UI, implement the code that interacts with the Authentication Flow API (using HTTP requests) as demonstrated in step 3 of the above figure.

Step 4: Finish the Authentication Flow

In an authentication flow with multiple steps, the custom UI and Authgear's authentication server may perform steps 3 and 4 in the above figure multiple times. In such cases, only the final response at the end of the authentication flow will include a finish_redirect_url.

You must redirect your user to the finish_redirect_url to complete the authentication flow.

To dive deeper into how to use the Authentication Flow API to power your custom UI, check out the following tutorials for your preferred programming languages and frameworks.

Implement Authentication Flow API using PHP

This guide shows how to setup custom login and signup pages using Authentication flow API.

You can create your own login and signup page from the ground up, using the Authentication flow API. In this guide, we'll implement Authentication Flow API using PHP.

Before we dive into the step-by-step guide, here are some key things you should know about working with the Authentication Flow API.

  • URL Query: When any of the Authgear SDKs redirects users to your Custom UI URL, Authgear adds some additional queries to the URL. These queries are required in order to get the finish_redirect_uri.

  • Endpoint: You can find your Authgear project domain from your application configuration page (usually under the Endpoint section) in Authgear Portal. The full endpoint is this Authgear domain followed by a valid path for an operation. For example, https://my-project.authgear.cloud/api/v1/authentication_flows to start an authentication flow. The two valid paths the API supports are /api/v1/authentication_flows and /api/v1/authentication_flows/states/input (which is for passing input to an existing authentication flow).

  • State Token: The Authentication Flow API supports authentication with multi-step UI just like the default authentication flow in Auth UI. State tokens can be used to make this type of type of authentication flow work. You can pass information about a previous step to the next step by using the state token. For example, using the state token in the result of step A as input in step B to continue using the state of the previous step.

  • Inputs: You can pass values to Authentication Flow API using the input or batch_input parameters in your HTTP request body. Use the batch_input to send multiple values as in an array and input when you are passing only 1 value.

  • Finish Redirect URI: A URL that you can use to redirect back to your app at the end of the authentication flow.

Pre-requisites

To follow along with the example in this post, you should have the following:

  • PHP installed on your local machine.

  • A code editor like VS Code, Sublime, Atom, or any editor you use for PHP development.

Now that you understand basic concepts about the Authentication API and what you need to follow along with our example, let's look at how to create our first custom login and signup page from scratch.

Part 1: Configure Authgear Project in Portal

In this section, you'll learn how to configure your Authgear project for the Authentication Flow API.

Step 1: Set up an Authgear Application

Navigate to Application > Add Application in Authgear Portal (or select an existing application then update the configuration).

Enter a name for your application and set the Application Type as OIDC Client Application. then click on the Save button.

Note: You can select any Application Type on the Portal depending on the nature of your client application that will be interacting with Authgear and your Custom UI.

Step 2: Add Authorized Redirect URIs

In this step, you'll add redirect URIs to your application. An Authorized Redirect URI should be a valid page on your application that you want Authgear to redirect users to at the end of the authentication flow.

To add a new URI, scroll down to the URIs section on the configuration page for the application you created in the previous step. Next, click on the Add URI button then enter a valid URL for your application. For this example, enter http://localhost:8081/ as a redirect URI.

Once you're done, save the changes to continue.

Step 3: Add Custom UI URI

The value for the Custom UI URI should be a link (absolute URL) to your custom login page. Authgear will redirect users to this page when they start an authentication request. Also, during redirect, Authgear will automatically include the URL query we mentioned earlier.

Now, still within the configuration page for your application, scroll down to the Custom UI section and add a link to your custom login page.

If you're testing your custom UI on a browser on the same device that you'll be using to serve the PHP code, you can enter your localhost URL in Custom UI URI. For example, you can use the following URL if you will run the PHP code on your local machine using port 8081 :

With that, we're done with the required configuration on the Authgear Portal. In the next part, we'll design some custom UI and implement the Authentication Flow API.

Step 4: Enable Email + Password Login Option and Disable 2FA

For our example app in this tutorial, users will be using their email and password to log in. Hence, you are required to enable this option in the Authgear Portal.

To do that, enable the "Email + Password" option under Authentication > Login Methods.

Also, disable 2FA (if enabled) so that the authentication flow does not include an extra step which our demo app will not cover. You can disable 2FA Requirements in Authentication > 2FA in the Authgear Portal.

Part 2: Implementing Authentication Flow API

Now that your Authgear project is set to use the Authentication Flow API, let's walk through the steps for creating a custom login and signup page. Our example app for this part of the guide uses PHP.

The application you'll build in this part is the same application your Custom UI URI should point to.

Step 1: Set up Authgear PHP Example App

Create a new folder on your computer for your PHP project using the following command or a file explore:

Change your current directory to the new folder using by running the following command:

For this example, we'll be using the oauth2-client package to interact with Authgear. Install the package using the following command:

Create the following files in and add the corresponding code to the files:

config.php:

Add the correct values for $clientID, $clientSecret, and $redirectUri from your Authgear application configuration page. The value for $appUrl should be your application endpoint.

index.php:

The above page will serve as a landing page for our example application. After a user clicks on the login link, they'll be redirected to your custom login page.

startLogin.php:

The code in startLogin.php initiates a regular Authgear authentication flow by redirecting the user to the authorization URL. In the case of our example, this authorization URL will point to our custom login page instead.

Step 2: Create Login Page

Still, in your PHP project folder, create a new login.php file and add the following code to it:

The above code creates a basic login page with email and password fields and a submit button.

On the first line of the code, the value for the URL Query that Authgear adds to your custom UI URI is read and stored in the $url_params variable. This value is required to finish the authentication flow.

Also in the above code, the form action points to a form.php with $url_params appended to the path. It is this form.php file that will process the form data and complete the login flow. We'll implement the file in a later step.

The following screenshot shows the output of the custom login page on a browser:

Step 3: Implement Login Flow

This is the part where you start to make interactions with the actual Authentication Flow API.

In this first interaction, we'll be making an HTTP request to the API endpoint to log a user into our application.

In the request, we'll send the email and password the user enters in the login.php page to the API endpoint to complete the authentication flow in a single step. What this means is that we'll initiate and finish the login flow using a single HTTP request. Unlike what we'll do in later steps for signup and OTP flows.

Now create a new form.php file and the following code to it:

Here are the key things the PHP code in form.php does at this point:

  • First, it reads the URL query from the form action and appends it to the API endpoint.

  • Then it makes a POST HTTP request to the endpoint with both Content-Type and Accept header values set to application/json. These header values are required for sending requests to the endpoint.

  • Next, the user input (email and password) from the form is sent in the body of the HTTP request. Also in the request body is type and name parameters that specify the type of authentication flow (login) and the name of the flow (default) respectively.

  • And finally, the value for finish_redirect_uri is read from the response of the HTTP request. This value is then used to redirect the user to the "finish redirect URI" to complete the login flow.

The HTTP response from the above request will look like this:

Step 4: Test the Login Flow

To your application, start your PHP server and try visiting the index.php from a web browser. If you have PHP installed on your local machine and the environment path set, you can start a PHP server for your project by running:

Now test the login flow by clicking on the login link on the landing page. You should be redirected to the custom login instead of the default AuthUI Authgear provides.

Enter a valid email and password combination and click the Login button like a normal user would test your implementation. The user should be redirected back to the application at the end of the authentication flow.

Step 5: Initialize Signup Flow

For this signup flow example, we'll be making two requests to the Authentication Flow API. In this step, we'll implement the first request which will only initialize the signup flow.

Create a new signup.php file inside your project folder and add the following code to it:

As you can see from the code snippet above, for this authentication flow, the type is "signup".

The initSignUp() method handles the step that starts the authentication flow for the specified type and returns a state_token that you can use to continue the flow.

Step 6: Create Signup Page

In this step, we'll create a sign-up page. The login page already contains a link that points to the sign-up page and also includes the URL Query.

To create the UI for the signup page, add the following code to the signup.php file just below the closing "?>" PHP embedded closing tag:

The above code implements a signup form that includes fields for users to enter their email and password and a submit button. The value for the <input type="hidden"> is the state_token returned from the previous. You need this state_token to proceed with the flow.

Step 7: Complete Signup Flow

Open form.php and add a new conditional block for when action=="signup" using the following code:

The above code sends the state_token from the previous step as part of the request body.

It also sends the email and password the user entered in the form.

On successful response, the code will redirect the user to the finish_redirect_url .

Test your implementation again using your frontend application and you should be able to register a new account using the custom UI.

Conclusion

Beyond login and sign-up, there's more you can do with the Authentication Flow API. However, the focus of this post has been to provide a guide for getting started with your first implementation of Authentication Flow API.

To learn more about supported flows, endpoints, their inputs, and responses, check out the official API Reference for Authentication Flow API.

For more details about the Authentication Flow API endpoints, inputs, response, and more visit the .

flowchart showing how authentication flow API works

installed on your computer.

An Authgear account. You can create one for free .

Enable Custom UI for your Authgear Project. to enable custom UI.

Alternatively, can use to get a public URL for your PHP application that's running locally. Then, enter the public URL from CloudFlare as your Custom UI URI.

We'll use the package to make HTTP requests to the Authentication Flow API. Hence, run the following command in the root folder of your project to install it:

API reference page
Implement Authentication Flow API using PHP
Implement Authentication Flow API using Express
http://localhost:8081/login.php
mkdir authgear-php-example
cd authgear-php-example
composer require league/oauth2-client
<?php
require 'vendor/autoload.php';

$appUrl = "";
$clientID = "";
$clientSecret = "";
$redirectUri = "http://localhost:8081/";

$provider = new \League\OAuth2\Client\Provider\GenericProvider([
    'clientId'                => $clientID,    // The client ID assigned to you by the provider
    'clientSecret'            => $clientSecret,    // The client password assigned to you by the provider
    'redirectUri'             => $redirectUri,
    'urlAuthorize'            => $appUrl.'/oauth2/authorize',
    'urlAccessToken'          => $appUrl.'/oauth2/token',
    'urlResourceOwnerDetails' => $appUrl.'/oauth2/userInfo',
    'scopes' => 'openid'
]);
?>
<?php
include "config.php";

// if code is set, get access token
if (isset($_GET['code'])) {
    $code = $_GET['code'];
    try {
        $accessToken = $provider->getAccessToken('authorization_code', [
            'code' => $code
        ]);
        $_SESSION['accessToken'] = $accessToken;
    } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
        // Failed to get the access token or user details.
        exit($e->getMessage());
    }
} 
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PHP Demo - Home</title>
</head>
<body style="background-color: #DEDEDE">
    <div style="max-width: 650px; margin: 16px auto; background-color: #FFFFFF; padding: 16px;">
        <h3>Hello world!</h3>
        <p>This demo app shows you how to add user authentication to your app using Authgear</p>
        <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        <?php
        if (isset($_SESSION['accessToken'])) {
            //if access token exists in session, attempt to fetch user info
            $resourceOwner = $provider->getResourceOwner($accessToken);
            $userInfo = $resourceOwner->toArray();

            echo "Welcome back " . $userInfo['email'];
            echo "<br/>";
            echo '<a href="'.$appUrl.'/logout">Logout</a>';
            
        } else { ?>
        <p><a href="startLogin.php">Login/Signup</a></p>
        <?php
        } 
        ?>
    </div>
</body>
</html>
<?php
include "config.php";

if (!isset($_GET['code'])) {
    // Fetch the authorization URL from the provider; this returns the
    // urlAuthorize option and generates and applies any necessary parameters
    // (e.g. state).
    $authorizationUrl = $provider->getAuthorizationUrl();

    // Get the state generated for you and store it to the session.
    $_SESSION['oauth2state'] = $provider->getState();

    // Redirect the user to the authorization URL.
    header('Location: ' . $authorizationUrl);
    exit;
}
?>
<?php $url_params = $_SERVER['QUERY_STRING']; 
?>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <title>Login</title>
</head>

<body>
    <div class="container pt-4">
        <form class="" action="<?php echo "form.php?action=login&" . $url_params; ?>" method="POST">
            <div class="">
                <label class="">
                    Email
                </label>
                <input name="email" type="email" class="form-control mb-2" placeholder="Enter your email" />
            </div>
            <div>
                <label>
                    Password
                </label>
                <input name="password" type="password" class="form-control mb-2" placeholder="Enter your password" />
            </div>
            <button type="submit" class="btn btn-primary">
                Submit
            </button>
        </form>
        <div>
            <span>Or</span>
            <a href="signup.php?<?php echo $url_params; ?>">Sign Up</a>
        </div>
    </div>
</body>
</html>
composer require guzzlehttp/guzzle
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;

$endpoint = "https://your-project.authgear.cloud"; //Check Authgear Portal for your endpoint

if (isset($_GET["action"])) {
    $action = $_GET["action"];

    if ($action == "login") {
        $url_params = $_SERVER['QUERY_STRING'];
        $url = $endpoint . "/api/v1/authentication_flows";

        $client = new Client();
        $headers = [
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ];
        $response = $client->post($url . "?" . $url_params, [
            "json" => [
                'type' => 'login',
                'name' => 'default',
                "batch_input" => [
                    [
                        "identification" => "email",
                        "login_id" => $_POST['email']
                    ],
                    [
                        "authentication" => "primary_password",
                        "password" => $_POST['password']
                    ]
                ]
            ],
            "headers" => $headers
        ]);

        if ($response->getStatusCode() == 200) {
            $response_array = json_decode($response->getBody(), true);
            header("Location: " . $response_array["result"]["action"]["data"]["finish_redirect_uri"]);
        }

    } 
}
{
    "result": {
        "state_token": "authflowstate_RB482Y95Q4BT8D4CAHXD499Y21MGAH2J",
        "type": "login",
        "name": "default",
        "action": {
            "type": "finished",
            "data": {
                "finish_redirect_uri": "https://cube-crisp-110.authgear-staging.com/oauth2/consent?code=HD2AS7394RJCGVYWYHQHXGDKYX8BZ28Q"
            }
        }
    }
}
php -S localhost:8081
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;

$endpoint = "https://your-project.authgear.cloud"; //Check Authgear Portal for your endpoint
function initSignUp() {
    $url_params = $_SERVER['QUERY_STRING'];
    $url = $endpoint . "/api/v1/authentication_flows?" . $url_params;

    $client = new Client();
    $headers = [
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
    ];
    $response = $client->post($url, [
        "json" => [
            "type" => "signup",
            "name" => "default"
        ],
        "headers" => $headers
    ]);

    $response_array = json_decode($response->getBody(), true);

    $state_token = $response_array["result"]["state_token"];
    return $state_token;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
        integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <title>Register</title>
</head>

<body>
    <div class="container pt-4">
        <form class="" action="form.php?action=signup" method="POST">
            <div class="form-group">
                <label class="">
                    Email
                </label>
                <input name="email" type="email" class="form-control mb-2" placeholder="Enter your email" />
            </div>
            <div class="form-group">
                <label>
                    Password
                </label>
                <input name="password" type="password" class="form-control mb-2" placeholder="Enter your password" />
            </div>
            <div class="form-group">
                <label>
                    Repeat Password
                </label>
                <input name="password" type="password" class="form-control mb-2" placeholder="Enter your password" />
            </div>
            <input type="hidden" name="state_token" value="<?php echo initSignUp(); ?>">
            <button type="submit" class="btn btn-primary">
                Submit
            </button>
        </form>
    <div>
</body>
</html>
else if ($action == "signup") {

    $url = $endpoint . "/api/v1/authentication_flows/states/input";

    $client = new Client();
    $headers = [
        'Content-Type' => 'application/json',
        'Accept' => 'application/json',
    ];
    $response = $client->post($url, [
        "json" => [
            'state_token' => $_POST['state_token'],
            "batch_input" => [
                [
                    "identification" => "email",
                    "login_id" => $_POST['email']
                ],
                [
                    "authentication" => "primary_password",
                    "new_password" => $_POST["password"]
                ]
            ]
        ],
        "headers" => $headers
    ]);

    if ($response->getStatusCode() == 200) {
        $response_array = json_decode($response->getBody(), true);
        header("Location: " . $response_array["result"]["action"]["data"]["finish_redirect_uri"]);
    }

}

Integrate

Integrate Authgear with your product

Cut down on implementation time by utilizing integrations that have been developed by Authgear. The Authgear platform is designed to be flexible, allowing you to meet your specific needs by customizing identity processes with your own code and easily integrating with other external applications and tools.

This set of how-to guides provides you with detailed instructions, code snippets, and configuration examples for each type of integration.

Composer
here
Contact us
CloudFlare Tunnel
GuzzleHttp

Add Custom Login/Signup UI to Native Apps

This guide shows how to use Custom Login/Signup pages UI in Native Apps

Implementing custom login and signup screens in any native application (Flutter, React Native, Kotlin, or iOS) doesn't require much change to the code for your existing native apps that use Authgear.

At the moment, we don't support direct interaction between your native code and the Authentication Flow API that powers custom UIs. That means you'll need to use the platform-specific SDKs we already provide and call the authenticate method to start the authentication flow.

In this guide, we'll teach you how to implement custom authentication UIs in a Flutter app using the Flutter SDK and Authentication Flow API.

Part 1: Configure Authgear Project in Portal

The main factor that enables custom UI in your Authgear application is specifying a custom UI URL in Authgear. Once this value is set, calling the authenticate method in any of the native SDKs will open the custom login/signup UI in a Web View instead of the default Auth UI.

Step 1: Set up an Authgear Application

If you do not already have an Authgear application, login to Authgear Portal and navigate to Application > Add Application to create an application.

Enter your application name and select Native App as Application Type then click the Save button to continue.

Step 2: Set Authorized Redirect URI

In this step, you'll add a URI that Authgear will use to return your application to the front of the screen when authentication is complete.

For our example Flutter app, this URI will start with the package name for our app followed by ://host/path.

To set the Redirect URI, scroll down to the Authorized Redirect URI under the URIs section of your application configuration page. Enter the correct URI for your application then click Save.

Note: You can find the package name for your Flutter app in android/app/build.gradle under android > namespace.

Step 3: Set Custom UI URI

Setting a value for Custom UI URI in Authgear Portal will redirect users of your application to your custom authentication UI instead of the default Auth UI. Hence, this is the most important step in adding custom login and signup UIs to your native application.

To set the Custom UI URI, scroll down to the Custom UI section on your application configuration page in the Authgear Portal. Then, add the URL to your custom login/signup page in the Custom UI URI text field.

Part 2: Implement Flutter Application

If you have an existing Flutter app that implements the default AuthUI, it may not require any change to make use of the Custom UI URI you've set in the previous step.

But if you're creating a new application, follow these steps:

Step 1: Create a Flutter App

Run the following command to create a new Flutter application:

flutter create myapp

Step 2: Install Authgear Flutter SDK

Now install the Authgear Flutter SDK by running the following command from your project directory:

flutter pub add flutter_authgear

Step 3: Implement Authgear

You can also find similar guides for other native platforms below:

Step 5: Test Your App

To test your application, run the following command:

flutter run

Tap on the Authenticate button when your app runs on a physical device or emulator. You should see the custom UI instead of the default Auth UI.

Conclusion

A very important to remember from the above guide is that when using custom authentication UI with a native application you can set up your app as you usually would with the default Auth UI. However, the main difference is that you should provide a link to your custom UI in the Authgear portal.

Manually Link OAuth Provider using Account Management API

Use the Account Management API to link OAuth provider.

The Management API provides a way to perform actions that you usually will do from the default /settings page using your own custom UI.

Account Management API for OAuth Provider

The account management API for OAuth providers allows developers to write their own custom code for linking a social or enterprise (OAuth) provider to user accounts on their Authgear provider. Developers can use this API to create a custom UI that their users can use to link one or more social login providers to their accounts.

The account management API for OAuth Provider has 2 endpoints that your code must make HTTP(s) POST requests to. A detailed description of the endpoints is given below:

1. /api/v1/account/identification

Use this endpoint to initiate the flow of linking an OAuth provider to an account. The endpoint requires a valid access token for the current user in the Bearer Authorization header.

Request Method:

POST

Request Header:

{
    "Authorization": "Bearer " + <ACCESS_TOKEN>
}

Request Body:

{
    "identification": "oauth",
    "alias": "google",
    "redirect_uri": "http://localhost:3000/linkcallback",
    "exclude_state_in_authorization_url": false
}
  • identification: Required. It must be the value oauth.

  • alias: Required. The alias of the OAuth provider you want the current account to associate with.

  • redirect_uri: Required. You have to specify your own redirect URI to your app or your website to receive the OAuth callback.

  • exclude_state_in_authorization_url: Optional. The default is false. When it is false, the authorization_url has a state parameter included, the token is bound to this state parameter. When it is true, the authorization_url has no state parameter included, the token is NOT bound to state. If you wish to use your own state, you must set this field to true.

Response:

{
  "result": {
    "token": "oauthtoken_abc123xyz",
    "authorization_url": "https://www.google.com?client_id=client_id&redirect_uri=redirect_uri"
  }
}
  • token: You store this token. You need to supply it after the end-user returns to your app.

  • authorization_url: You MUST redirect the end-user to this URL to continue the authorization code flow. If exclude_state_in_authorization_url is false, it has the state parameter included.

2. /api/v1/account/identification/oauth

Call this endpoint from your redirect URI to finish the process of linking an OAuth provider.

Request Method:

POST

Request Header:

{
    "Authorization": "Bearer " + <ACCESS_TOKEN>
}

Request Body:

{
    "token": <TOKEN>,
    "query": <URL_QUERY>
}
  • query: The query of the redirect URI.

Response:

{"result":{}}

How to Link OAuth Provider

In this example, we'll link Google as the OAuth provider.

Step 1: User Login (Get Access Token)

The account manage API requires a user's valid access token to work. Hence, you must first authenticate the user using another identity first.

Set up your application to allow users to log in using Authgear and obtain an access token.

Step 2: Initiate OAuth Link Flow

Now that your application can obtain a valid access token for a user, you'll make an HTTP(s) request to the /api/v1/account/identification endpoint to initiate the OAuth provider linking flow.

Use the following code to send the HTTP(s) request:

app.get("/link", async (req, res) => {
    const endpoint = `<YOUR_AUTHGEAR_ENDPOINT>/api/v1/account/identification`;
    const accessToken = req.session.accessToken; //TODO Get access token for user here. The example retrieves the value stored in session cookies
    
    try {
    
        const initiateAccountLink = await axios.post(endpoint, 
        {
            "identification": "oauth",
            "alias": "google",
            "redirect_uri": `http://localhost:3000/linkcallback`,
            "exclude_state_in_authorization_url": false
        }, {
            headers: { "Authorization": "Bearer " + accessToken }
        });
        req.session.token = initiateAccountLink.data.result.token;
        
        res.send("linking initiated!"); // TODO Replace this link with Login with provider link instead
    } catch(error) {
        let errorInfo = error;
        if (error.response) {
            errorInfo = error.response.data;
        }
        res.send("An error occurred " + JSON.stringify(errorInfo));
    }

});

In the code above, the body of the HTTP(S) request includes the identification type which is oauth because we're trying to add a new OAuth Provider as an identity for a user's account. The value of alias is google because the OAuth provider to be added is Google.

The link in redirect_uri is a page on the example application that will handle the callback from the OAuth provider. We will implement this page in the next step.

The response from the /api/v1/account/identification endpoint should look like this:

{
  "result": {
    "token": "oauthtoken_abc123xyz",
    "authorization_url": "https://www.google.com?client_id=client_id&redirect_uri=redirect_uri"
  }
}

Step 3: Get OAuth Provider's Authorization URL

The response for the HTTP(s) request in Step 2 includes an authorization_url field. That field contains the OAuth provider's authorization URL. Your application can redirect users to authorization_url for them to grant authorization on the OAuth provider's website.

Replace the line with // TODO in Step 2 with the following code to use the value of authorization_url in a hyperlink that users can click:

res.send(`
    <a href="${initiateAccountLink.data.result.authorization_url}">Link Google Account</a>
    `);

Step 4: Finish Linking Account

The final step for linking an OAuth provider is to implement the callback URL that the OAuth provider will be redirecting users back to after authorization. This is where your application will be making an HTTP(S) request to the second endpoint (/api/v1/account/identification/oauth).

For this example, we'll create a "/linkcallback" route to handle the redirect using the following code:

app.get('/linkcallback', async (req, res) => {
    const endpoint = `<YOUR_AUTHGEAR_ENDPOINT>/api/v1/account/identification/oauth`;
    const accessToken = req.session.accessToken;
    const currentUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
    const queryParams = new URL(currentUrl).search;;
    
    try {
        const finishLink = await axios.post(endpoint, {
            "token": req.session.token,
            "query": queryParams,
        }, 
        {
            headers: { "Authorization": "Bearer " + accessToken }
        });
    
        res.send(JSON.stringify(finishLink.data));
    } catch(error) {
        let errorInfo = error;
        if (error.response) {
            errorInfo = error.response.data;
        }
        res.send("An error occurred " + JSON.stringify(errorInfo));
    }

});

The above code sends the token (returned in the response to the previous HTTP(S) request) and the query parameters added to the redirect URI by the OAuth provider in an HTTP(S) request to the finish endpoint. Both parameters are required.

The following will be the response of the endpoint when the OAuth provider is linked successfully:

{"result":{}}

Implement Authentication Flow API using Express

This post provides a simple guide for implementing a custom email + password login and signup pages using Authentication Flow API and Express.

With the Authentication Flow API, you can replace the default Auth UI provided by Authgear with your own custom UI built from the ground up.

In this post, we'll walk you through an example of building your own custom login and signup pages using Express and the Authentication Flow API.

Before we continue, it's important for you to familiarize yourself with the following concepts about the Authentication Flow API:

  • URL Query: This is an additional set of URL query parameters that Authgear adds to your Custom UI URI during the initialization of the authentication flow. The initial request to the Authentication Flow API must include this URL query in order to return get value for finish_redirect_uri at the end of the flow.

  • Endpoint: Your Authgear project's domain is visible on your application configuration page in Authgear Portal, under the Endpoint section. Your full endpoint is your Authgear domain followed by a valid path for an operation (such as starting a new authentication flow, or sending input to an existing flow. For example, https://my-project.authgear.cloud/api/v1/authentication_flows to start an authentication flow and https://my-project.authgear.cloud/api/v1/authentication_flows/states/input to send input to an existing flow.

  • State Token: The Authentication Flow API supports authentication with multi-step UI just like the default authentication flow in Auth UI. State tokens can be used to make this type of type of authentication flow work. You can pass information about a previous step to the next step by using the state token. For example, using the state token in the result of step A as input in step B to continue using the state of the previous step.

  • Inputs: You can pass values to Authentication Flow API using the input or batch_input parameters in your HTTP request body. Use the batch_input to send multiple values as in an array and input when you are passing only 1 value.

  • Finish Redirect URI: This is a URL that you can use to redirect back to your app at the end of the authentication flow.

Note: In order to follow this tutorial and implement the example app, you need to enable a login method that supports "Email and Password" under Authentication > Login Methods in Authgear Portal. Also, disable 2FA Requirements from Authentication > 2FA in Authgear Portal.

Pre-requisites

In order to follow along with the example in this post, you should have the following:

  • Node.js installed on your local machine.

  • A code editor such as VS Code, Sublime, Atom, etc.

  • Be familiar with CLI tools like npm.

Next, set up your Authgear project to use custom authentication UI by following the steps below.

Part 1: Configure Authgear Project in Portal

An important part of getting your application ready to use custom authentication UI is to configure your Authgear project in Portal. In this section, we'll cover the configuration required for the example app.

Step 1: Set up Authgear Application

Login to the Authgear Portal and navigate to the Application section. Select an existing application and modify it or click on the Add Application button to create a new application.

Configure your application using the following details:

  • Application name: My app <or any name of your choice>

  • Application type: OIDC Client Application

Once you're done, click on the Save button to continue.

Note: You can select any Application Type on the Portal depending on the nature of your client application that will be interacting with Authgear and your Custom UI.

To follow this example, select OIDC Client Application as your Application type.

Step 2: Add Authorized Redirect URIs

An Authorized Redirect URI is a page on your application that you want Authgear to redirect users to at the end of an authentication flow.

To add an Authorized Redirect URI, scroll to the URIs section on your Authgear application configuration page. Click on the Add URI button then enter a valid URI for your application.

For our example, the redirect URI will be:

http://localhost:3000/

Once you're done, click on the Save button to keep your changes.

Step 3: Set Custom UI URI

To use your custom authentication UI with Authgear, you need to specify the URI for your custom UI in the Authgear portal using the custom UI URI field. This will cause your application to show the custom UI instead of the default Auth UI during login/sign. The custom UI URI is basically a link to your custom login page.

Since we'll be testing the example app on a browser that runs on the same computer as the Express server, you can use the following value for the Custom UI URI:

http://localhost:3000/login

To set the custom UI URI, scroll to the Custom UI section on your application configuration page and paste the URL (e.g the unique public URL from CloudFlare Tunnel) in the Custom UI URI text box.

Note: For our example app, you must include the /login path in the URL so that the user is redirected straight to our login route.

That concludes all the configuration requirements in the Authgear portal for this example.

Step 4: Enable Email + Password Login Option and Disable 2FA

For our example app in this tutorial, users will be using their email and password to log in. Hence, you are required to enable this option in the Authgear Portal.

To do that, enable the "Email + Password" option under Authentication > Login Methods.

Also, disable 2FA (if enabled) so that the authentication flow does not include an extra step which our demo app will not cover. You can disable 2FA Requirements in Authentication > 2FA in the Authgear Portal.

Part 2: Implementing Authentication Flow API

In this part of the guide, we'll implement custom login and signup pages using Express and the Authentication Flow API.

The application you'll build in this part is the same application your Custom UI URI should point to.

Step 1: Setup Authgear Express Example App

Create a basic Express application for your Authgear project.

To do that, first run the following commands on your computer to create a new project folder and install all the necessary dependencies:

Create project folder/directory:

mkdir authgear-express-example

Change your working directory to the new folder by running the following command:

cd authgear-express-example

Install Express:

npm install express

For our example application, we'll be using the Axios node package to make HTTP requests. Run the following command to install Axios in your project:

npm install axios

Install dotenv. We'll use this package to enable the use of .env file to store project configuration:

npm install dotenv

After installing the above dependencies, create a new app.js file in the project directory you created earlier. Add the following code to the file:

const express = require('express');
const axios = require('axios');
require("dotenv").config();

const app = express();
app.use(express.urlencoded({ extended: true }));
const port = process.env.PORT || 3000;

const config = {
  client: {
    id: process.env.CLIENT_ID,
    secret: process.env.CLIENT_SECRET,
    redirect_url: process.env.REDIRECT_URL
  },
  auth: {
    tokenHost: process.env.AUTHGEAR_ENDPOINT,
    tokenPath: '/oauth2/token',
    authorizePath: '/oauth2/authorize'
  },
};

app.get('/', async (req, res) => {

  if (req.query.code != null) {
    const data = {
      client_id: config.client.id,
      client_secret: config.client.secret,
      code: req.query.code,
      grant_type: 'authorization_code',
      response_type: 'code',
      redirect_uri: config.client.redirect_url,
      scope: "openid"
    };

    try {
      const getToken = await axios.post(`${config.auth.tokenHost}${config.auth.tokenPath}`, data, {
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
      });

      const accessToken = getToken.data.access_token;

      //Now use access token to get user info.
      const getUserInfo = await axios.get(`${config.auth.tokenHost}/oauth2/userinfo`, { headers: { "Authorization": "Bearer " + accessToken } });
      const userInfo = getUserInfo.data;
      res.send(`
        <div style="max-width: 650px; margin: 16px auto; background-color: #EDEDED; padding: 16px;">
          <p>Welcome ${userInfo.email}</p>
          <p>This demo app shows you how to add user authentication to your Express app using Authgear</p>
          <div>
            <pre>${JSON.stringify(userInfo, null, 2)}</pre>
          </div>
            <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
          
        </div>
    `);
    } catch (error) {
      res.send("An error occurred! Login could not complete. Error data: " + JSON.stringify(error.response.data));
    }
  }

  else {
    res.send(`
      <div style="max-width: 650px; margin: 16px auto; background-color: #EDEDED; padding: 16px;">
        <p>Hi there!</p>
        <p>This demo app shows you how to add user authentication to your Express app using Authgear</p>
          <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        <a href="/startLogin">Login</a>
      </div>
    `);
  }
});

app.get('/startLogin', (req, res) => {
  res.redirect(`${config.auth.tokenHost}${config.auth.authorizePath}/?client_id=${config.client.id}&redirect_uri=${config.client.redirect_url}&response_type=code&scope=openid`);
});

Create a .env file then add the following code to it:

CLIENT_ID=paste_your_client_id_here
CLIENT_SECRET=paste_your_client_id_here
AUTHGEAR_ENDPOINT=paste_your_client_id_here
REDIRECT_URL=http://localhost:3000/

Add the correct values from your Authgear application configuration page in the .env file.

At the end of this step, you should have an Express application that can connect to Authgear. However, we are yet to implement the custom login/signup page. In the next steps, we'll implement both pages.

Step 2: Create Login Page

Add the following code to your app.js file just below the app.get('/startLogin',...) route:


function rawURLQuery(url) {
    const index = url.indexOf('?');
    return (index >= 0) ? `?${url.substr(index + 1)}` : "";
}

app.get('/login', (req, res) => {
    //get URL query
    const URLQuery = rawURLQuery(req.url);
    res.send(`
    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
            integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <title>Login</title>
    </head>

    <body>
        <div class="container pt-4">
            <form class="" action="./login" method="POST" enctype="application/x-www-form-urlencoded">
                <div class="">
                    <label class="">
                        Email
                    </label>
                    <input name="email" id="email" type="email" class="form-control mb-2" placeholder="Enter your email" />
                </div>
                <div>
                    <label>
                        Password
                    </label>
                    <input name="password" id="password" type="password" class="form-control mb-2" placeholder="Enter your password" />
                </div>
                <input type="hidden" name="url_query" value="${URLQuery}">
                <button type="submit" class="btn btn-primary">
                    Submit
                </button>
            </form>
            <div>
                <span>Or</span>
                <a href="/signup?${URLQuery}">Sign Up</a>
            </div>
        </div>
    </body>
    </html>
    `);
});

app.listen(port, () => {
    console.log(`server started on port ${port}!`);
});

The above code sets up a basic email + password login page using Express.

The rawURLQuery() function extracts the URL query we mentioned earlier from the URL of the login page. The code includes the query as the value for an <input type="hidden"> so that we can include the value in the request we'll make to the Authentication Flow API later.

The following screenshot shows the output of the login page in a browser:

Step 3: Implement Login Flow

Now your application needs to make an HTTP request to the Authentication Flow API with the user inputs to authenticate them.

First, we'll create a userLogin() function that sends the HTTP request. To do that, add the following code to your app.js just above the declaration of the rawURLQuery() function:

const endpoint = process.env.AUTHGEAR_ENDPOINT;

async function userLogin(email, password, url_query) {
    const url = `${endpoint}/api/v1/authentication_flows?${url_query}`;

    const input = {
        "type": "login",
        "name": "default",
        "batch_input":
            [
                {
                    "identification": "email",
                    "login_id": email
                },
                {
                    "authentication": "primary_password",
                    "password": password
                }
            ]
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        const startLogin = await axios.post(`${url}`, input, {
            headers: headers
        });
        return startLogin;
    }
    catch (error) {
        return error.response;

    }
}

Here are a few key things to note about the above code:

  • The code initiates an Authentication Flow API request of type login and finishes the entire login flow in a single step (one HTTP request).

  • As we mentioned earlier, the URL query from Authgear is added to the API endpoint for the initial request.

  • The user inputs (email and password) are sent in the request body using the batch_input parameter.

The structure of the HTTP response will look like this:

{
    "result": {
        "state_token": "authflowstate_RB482Y95Q4BT8D4CAHXD499Y21MGAH2J",
        "type": "login",
        "name": "default",
        "action": {
            "type": "finished",
            "data": {
                "finish_redirect_uri": "https://cube-crisp-110.authgear-staging.com/oauth2/consent?code=HD2AS7394RJCGVYWYHQHXGDKYX8BZ28Q"
            }
        }
    }
}

Now add the following code after the app.get('/login',...) route to create a new route that handles the action of submitting the login form:

app.post('/login', async (req, res) => {
    try {
        const apiResponse = await userLogin(req.body.email, req.body.password, req.body.url_query);
        if (apiResponse.status == 200 && apiResponse.data.result.action.data.finish_redirect_uri !== undefined) {
            res.redirect(apiResponse.data.result.action.data.finish_redirect_uri);
        } else {
            //this code will run usually when your authentication flow starts without the URL Query in the initial request.
            res.send(apiResponse.data);
        }
    }
    catch (error) {
        console.log(error);
        res.send("Error: authentication failed!");
    }
});

Once the login flow is complete and a finish_redirect_uri is returned, we redirect the user to this URL for Authgear to finish the authentication process and redirect the user back to your application.

Step 4: Test the Login Flow

To test your progress so far, start your Express app by running the following command:

node app.js

Now open your app in a web browser by visiting localhost:3000. Once the page loads, click on the Login link. You should be redirected to the custom login page instead of the default Auth UI by Authgear.

Enter a valid email and password and click the Submit button. You should be redirected back to your application on successful login.

Step 5: Initialize Signup Flow

This step includes an example of using the Authentication Flow API for user signup. Unlike in the previous login flow example, this time we'll use the API to perform a signup flow using 2 steps(also 2 HTTP requests).

The first step is to initialize the signup flow. To do that, create an initSignUp() function just after the userLogin() function in app.js using the following code:

//function for first step of signup flow
async function initSignUp(url_query) {
    const url = `${endpoint}/api/v1/authentication_flows?${url_query}`;

    const input = {
        "type": "signup",
        "name": "default"
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        startSignUp = await axios.post(url, input, {
            headers: headers
        });

        return startSignUp.data.result.state_token;
    }
    catch (error) {
        return error.response;
    }
}

Here is a breakdown of what the above code does:

  • First, in the code, the value for the URL query is added to the Authentication Flow API endpoint so as to meet the requirement for getting the finish_redirect_uri at the end of the flow.

  • The type of authentication flow is also specified as signup in the input variable that's passed in the HTTP request body.

  • The function returns the value of state_token from the HTTP request response. This value is required in the next step (request) to continue the signup flow.

Step 6: Create Signup Page

To create the actual page with a signup, add the following code just after the app.post('/login',...) route in app.js:

app.get('/signup', async (req, res) => {
    const URLQuery = rawURLQuery(req.url);
    res.send(`
        <!DOCTYPE html>
        <html lang="en">
        
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
                integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
            <title>Register</title>
        </head>
        
        <body>
            <div class="container pt-4">
                <form class="" action="./signup" method="POST" enctype="application/x-www-form-urlencoded">
                    <div class="form-group">
                        <label class="">
                            Email
                        </label>
                        <input name="email" type="email" class="form-control mb-2" placeholder="Enter your email" />
                    </div>
                    <div class="form-group">
                        <label>
                            Password
                        </label>
                        <input name="password" type="password" class="form-control mb-2" placeholder="Enter your password" />
                    </div>
                    <div class="form-group">
                        <label>
                            Repeat Password
                        </label>
                        <input name="password2" type="password" class="form-control mb-2" placeholder="Enter your password" />
                    </div>
                    <input type="hidden" name="state_token" value="${await initSignUp(URLQuery)}">
                    <button type="submit" class="btn btn-primary">
                        Submit
                    </button>
                </form>
            <div>
        </body>
        </html>
    
    `);
});

The above code contains the HTML code for rendering a simple email and password signup page. It also calls the initSignUp() to start the authorization flow and add the state token in an <input type="hidden">.

Step 7: Complete the Signup Flow

To complete the signup flow, first create a submitSignUpData() function by adding the following code just after the initSignUp() function in app.js:

async function submitSignUpData(email, password, state_token) {
    const url = `${endpoint}/api/v1/authentication_flows/states/input`;

    const input = {
        "state_token": state_token,
        "batch_input":
            [
                {
                    "identification": "email",
                    "login_id": email
                },
                {
                    "authentication": "primary_password",
                    "new_password": password
                }
            ]
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        const sendSignUpData = await axios.post(`${url}`, input, {
            headers: headers
        });
        return sendSignUpData;
    }
    catch (error) {
        console.log(error.response);
        return error.response;
    }
}

The above code implements the second step of the signup flow. It takes the state token from the first step and sends it in the second HTTP request so that the flow can continue.

Next, add the following code just after the app.get('/signup',...) route:

app.post('/signup', async (req, res) => {
    try {
        const apiResponse = await submitSignUpData(req.body.email, req.body.password, req.body.state_token);
        if (apiResponse.status == 200 && apiResponse.data.result.action.data.finish_redirect_uri !== undefined) {
            res.redirect(apiResponse.data.result.action.data.finish_redirect_uri);
        } else {
            //this code will run usually when your authentication flow starts without the URL Query in the initial request.
            res.send(apiResponse.data);
        }
    }
    catch (error) {
        console.log(error)
        res.send("Error: authentication failed!");
    }
});

The above code calls the submitSignUpData() function which initiates the second step of the signup flow and submits the user inputs. At the end, the user is redirected to the finish_redirect_uri again to complete the authentication process.

Conclusion

Just like we've implemented custom UI for email and password authentication in this example, you can design custom UIs for other authentication flows that Authgear supports. For example, OTP and TOTP.

To learn more about all the endpoints the Authentication Flow API supports, and their inputs and outputs, you should check out the API reference page for Authentication Flow API.

Custom UI

Resources about setting up your own custom User Interface for Login, Signup, Account recovery and more.

You can build your own custom UI powered by the new Authentication Flow API. Here are some resources for getting started:

Implement a custom account recovery UI using Authentication Flow API

Guide on how to implement your own account recovery UI powered by the Authentication Flow API

In this guide, you'll learn how to implement your own custom account recovery page that is powered by the Authentication Flow API.

Before we continue, here's an overview of our objectives for this post:

What we will build

At the end of this guide we'll build a custom account recovery UI using Express.js that will do the following:

  • Allow users to enter the phone number associated with their account as login ID.

  • Send an account recovery code to the phone number.

  • Provide a UI for the user to enter and verify the recovery code.

  • Finally, a UI for the user to set a new password for their account.

Pre-requisites

To follow this guide, you should have the following:

  • A code editor like VS Code, Sublime, Atom, or any editor you already use for JavaScript development.

  • Be comfortable working with CLI tools like NPM.

Step 1: Set up your Authgear Project to use Custom UI

Using custom UI in your Authgear application requires setting the value for Custom UI URI to where your custom UI is hosted.

To set this value, log in to the Authgear Portal and navigate to Applications then select your application. Next, in your application's configuration page, scroll down to the Custom UI section and enter the URL for your custom UI.

For the example in this post, we'll be using CloudFlare Tunnel to expose the custom UI we'll be building so that we can have a public URL to enter in the Custom UI URI field in our Authgear application configuration.

If you're new to the Authentication Flow API, check this getting started post [HERE(LINK)] to learn more about configuring your project for the API.

Step 2: Create Express project

Now let's create the Express project that we'll be using to implement the account recovery Custom UI.

To create a new Express project create a new folder with the name "custom-recovery" on your computer using a file explorer or using the following command in PowerShell or Terminal:

This folder will serve as your Express project folder.

Next, install the Express package by running the following command:

Finally, create a new JavaScript file with the name "app.js" in the new folder you created earlier. This is the file where we'll implement our application logic.

Add the following code to the new app.js file:

At this point, test your work so far by running the following command from the root of your Express project folder:

Step 3: Create account recovery page

Here we'll create the UI for the first page of the recovery flow. This will be a basic webpage with an input field for the user to enter their phone (login id) and a submit button.

Open app.js in your code editor and update the content of the app.get('/recovery') route to the following:

The above code refers to a rawURLQuery() and initRecovery() functions that we've not implemented yet. We'll implement the first function in this step and the second in the next step.

The form we created using the above code looks like this:

Look for the following line of code in your app.js file:

Then add the following code on a new line just below it:

The above code implements the rawURLQuery() function we mentioned earlier. This function is a helper that helps us extract URL Query from the current request. We need a special URL Query from Authgear in order to get the finish redirect URI at the end of our recovery flow. You can learn more about the URL Query [HERE(LINK)].

Step 3: Initialize the recovery flow

In this step, we'll initialize a new authentication flow of type account_recovery.

For this step and other steps that follow, we'll be making HTTP request to the Authentication Flow API using the Axios node package. Install Axios by running the following command:

Import Axios to your project by adding the following code to the top of app,js:

Next, again, look for the following line in your app.js file:

Add the following code on a new line just below it:

The above code implements the initRecovery() function. The function sends the HTTP request that initializes a new account recovery flow and returns a state_token. We'll use this state_token to continue to the next step of the flow. Hence we are passing the value for state_token to the next step using <input type="hidden">.

The response to the HTTP request looks like this:

Step 4: Send recovery code

In this step, we'll implement the code that will send the recovery code to the user's phone after they enter their phone number on the form and click submit.

Add a new beginRecovery() function to app.js (just below the initRecovery() function) using the following code:

The above code sends a request with the user's phone number (login_id) and the position of the channel (index) to which the code should be sent.

To enable Express to process form data correctly, add the following code on a new line to the top of app.js (just below const app = express();):

Now create a POST route that will call the beginRecovery() function by adding the following code just below the app.get('/recovery') route:

The above code will redirect the user to a verifyRecovery page if a recovery code was sent successfully. We'll implement this page in the next step.

The above code uses express-session, so install the package by running the following command:

Then import express-session to your app.js by adding this code to the top of the file:

Finally, enable express-session as a middle-ware by adding for following code on a new line at the top of app.js (just below const app = express();):

Step 5: Verify recovery code

Now let us implement the page where the user can enter the recovery code they got for verification.

Add a new route to app.js to create the UI for the verification page:

Here is what the verify recovery code page looks like:

Next, add a new verifyRecoveryCode() function to app.js using the following code:

The above code will send the request to the Authentication Flow API with the account recovery code a user enters.

To finish up the recovery code verification process, add a new route that will handle the form submission using the following code:

The code sample above will redirect the user to a setPassword page after successful verification of the recovery code they entered. In the next step, we'll implement the page where the user can set a new password.

Step 6: Implement set new password page

The final step of the account recovery process is for the user to set a new password for their account. In this step, we'll implement the UI for that.

First, add a new route to your app.js to create the UI using the following code:

The above code will implement a page that looks like this:

Add a new recoverySetPassword() function to app.js using the following code:

Next, create the route that will handle the submission of the set new password form using the following:

If the new password is set successfully, the above code will return control to Authgear to complete the rest of the authentication flow and return to your application. This is done by redirecting the client to the finish_redirect_uri.

Conclusion

And there you have it, you've successfully implemented your own custom password recovery UI powered by the Authentication Flow API.

For our example application, we used the phone number as login_id and the channel for receiving the recovery code. In a real app, you may use another channel such as email instead or even support both depending on what is available for the user.

Track User Before and After Signup

Learn how to track a user that signs up from a particular source or campaign.

In this guide, you'll learn how to track users from a particular source before and after they sign up. For example, knowing how many people sign up for your application through a signup link that you have included in a blog post or an email campaign.

Pre-requisites

To follow this guide, you need to have the following:

  • A free Authgear account.

  • An application in the Authgear Portal and note down the configuration of the application.

  • A client application that is written in your preferred language or framework.

What We'll Build

For this guide, we'll build a demo Express application that has the following features:

  • Read a source URL parameter defined by you (the developer).

  • Send the value of the source parameter to the Authgear authorization server using the OAuth 2.0 state parameter.

  • Read the value of state returned after user authorization (sign up) and log the value in a database or analytics system like Mixpanel.

What is the OAuth 2.0 State Parameter?

The authorization server (Authgear) will include the same state parameter value when redirecting the user-agent back to the client application. As a result, the client application can retrieve the value of state returned to verify that it is the origin of the authorization request.

We will use the above behavior of the authorization process to track a user before and after they sign up.

How to Track a User Who Signs Up from a Particular Source

The following steps show the steps for building a simple application that is capable of tracking users before and after they sign up.

Step 1: Set Up Your App to Use Authgear

1. Express:

2. Axios:

Next, inside the project directory, create a new app.js file then add the following code to the file:

You can get the correct configuration values (CLIENT_ID, CLIENT_SECRET, REDIRECT_URL, and AUTHGEAR_ENDPOINT) from the Applications section of the Authgear Portal.

Step 2: Add State Parameter to Authorization Request

In this step, we'll implement a /login route in the demo application. This route will support a source query parameter, for example, /login?source=002.

Add the following code to the end of app.js to implement the /login route:

The above code will check if the source parameter is included in the HTTP request to the /login route. If there is a source parameter, the value of the source will be added to the authorization URL's state parameter.

The following is an example of a login URL that includes the source parameter:

Step 3: Read the Value of State After Authorization

As described earlier, Authgear will return whatever value you put in the state parameter of the authorization URL. In the last step, we will read the value of the source parameter from the /login route and pass it to the state parameter. In this step, we'll read the state parameter that Authgear returns in the redirect URI for the initial value we passed (source).

To do this, we'll add a / route to resolve our redirect URI. Add the following code to the end of app.js to implement the route:

The sourceFromState constant holds the value for the state parameter in the redirect URI. You can save this value to a database to track that the user has successfully signed up using the link with the source value in your original campaign link. You may also send this link to an analytic tool like Mixpanel to track the user and source.

To run the demo app, run the following command in the terminal:

Then, open http://localhost:3000/login?source=002 on a browser. You can change 002 to any random string that you wish to use for tracking a source or campaign. Also, be sure to add http://localhost:3000 as a redirect URL for your application in the Authgear Portal.

Add custom fields to a JWT Access Token

Learn how to add custom attributes to a JWT Access Token using Authgear

JWTs (JSON Web Tokens) are a common method for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. With Authgear, it is straightforward to add custom fields to your JWT access tokens.

Prerequisites

Enable Access Token for your App

Make sure the option Issue JWT as access token is enabled in your Application settings in the Portal.

  1. Navigate to the Applications tab and choose the existing App.

  2. On the App Configuration dashboard, locate the "Access token" section.

  3. Make the toggle Issue JWT as access token switch on.

Create a new Event Hook

  1. Navigate to your Authgear Dashboard's Advanced->Hooks section.

  2. Add a new Blocking Event.

  3. Choose the Block Hook Type as the TypeScript and set the Event option to JWT access token pre-create. You will write a new Typescript function from scratch.

  1. Click on Edit Script under the Config option.

  2. Copy and paste the following into the editor:

  1. Click on Finish Editing.

  2. Back to the Hooks page from the navigation bar and click on the Save button at the top of the page.

Verify the Custom Field in a JWT token

There are two ways to test it:

  • If you created the application type OIDC Client Application, you need to follow the steps below. Expand it to see instructions.

Verify the custom field in the JWT Token with OIDC Client Application

This part explains how to retrieve an access token using OpenID App Endpoints and check if newly added custom attributes are in place in the JWT Access token.

Prerequisites

  • Make sure that you have a registered app type of OIDC Client Application in Authgear Portal.

Step 1: Obtain the necessary parameters

Open your OpenID Auth App configuration, and find Client ID, Client Secret, and check Authorization, and Token endpoints. You will use them in the next steps.

Step 2: Construct the authorization endpoint URL

The URL for this endpoint is usually provided by the authorization server and includes parameters specifying the requested scope, client_id, and response_type. Here's an example URL for the authorization endpoint:

Replace <YOUR_AUTHGEAR_ENDPOINT> with your Authgear server's domain, YOUR_CLIENT_ID with your application's Client ID from OpenID App.

Step 3: Redirect the user to the authorization endpoint

Next, you need to redirect the user to the authorization endpoint. You can just put the URL in your browser and log in with a user credential you are interested to retrieve an access token for. After successful authentication and consent, the Authgear will redirect the user back to your specified redirect URI, including an authorization code as a query parameter. You will need the code in the next step

Step 4: Obtain an access token

You need to make a request to the OpenID App's Token endpoint to exchange the authorization code we retrieved in the previous step for an access token.

  • The token endpoint URL is usually something like https://<YOUR_AUTHGEAR_ENDPOINT>/oauth2/token.

  • Include parameters such as grant_type=authorization_code, code=AUTHORIZATION_CODE, client_id=YOUR_CLIENT_ID, client_secret=YOUR_CLIENT_SECRET, and redirect_uri=YOUR_REDIRECT_URI.

  • Make a POST request to the token endpoint to obtain the access token.

Step 5: Verify custom attributes in the access token

\

This URL is a publicly accessible link on the web that hosts the code that implements your custom UI and does the actual interaction with the Authentication Flow API. Check out our examples for implementing custom login and signup UI pages using and to learn more.

Make sure you have your local machine set up for Flutter development before you run the above command. See the official guide for setting up Flutter . Once you're down, open the new project folder in your preferred code editor (VS Code or Android Studio).

To implement Authgear in your Flutter app use the SDK, please follow these instructions on the .

To learn more about using Authgear in your Flutter app, check out this page about the .

token: The token you received in the response of the endpoint.

See our section for a detailed guide for your preferred programming language or framework.

An Authgear account. You can create one for free .

Enable Custom UI for your Authgear Project. to enable custom UI.

authgear portal app config redirect uri

Alternatively, you can get a public URL for our local Express app with CloudFlare Tunnel. See more instructions on how to set up CloudFlare tunnel on your local machine .

You can find the complete code for the example application in this post in our .

installed on your local machine.

Last but not least, an Authgear account. Sign up for free .

Then go to your preferred web browser and visit .

The includes an optional state parameter. The value of the state parameter can be any random string or number defined by a client application (e.g a web or mobile that uses Authgear for user authentication) before the client makes an authorization request. In simple terms, the state parameter is added to the authorization URL as a URL query.

First, create a new project directory and open it. The demo application for this guide is a simple application that use Axios to make HTTP requests. Hence, install both packages using the following commands:

This how-to guide will walk you through the process of adding custom fields such as attributes to a JWT access token payload using Authgear and Javascript .

Here's an example of the and an explanation of their values.

You can also to on the Authegear Portal.

An Authgear account: You need an Authgear account to follow this guide. If you don't have one, you can on the Authgear website.

A Registered App: You need a (client) in Authgear.

Log into your .

With the use of Hooks, Authgear provides flexibility for adding custom logic to your authentication pipeline. You can create a Hook which is triggered any of these about to occur. For example, oidc.jwt.pre_create the event happens just before issuing the JWT access token and it can be used to put extra information into the token.

In the above code, we are importing the necessary modules such as HookResponse and EventOIDCJWTPreCreate which are types from the Authgear hook . We modify the JWT payload by adding (e.payload.user.standard_attributes) and (e.payload.user.custom_attributes) of the user.

You can do this by on your application server side using a JWT decoder and inspecting the payload.

Finally, we can debug the access token using the to see if the custom field and value we added previously are there inside the JWT payload.

PHP
JavaScript(Express)
here
Authgear Flutter SDK guide page
React Native
Android SDK
iOS
Xamarin
Authgear Flutter SDK
Getting Started
here
Contact us
here
Authentication Flow API Example GitHub repository
Authentication Flow API
Implement Authentication Flow API using PHP
Implement Authentication Flow API using Express
Add Custom Login/Signup UI to Native Apps
/api/v1/account/identification
mkdir custom-recovery
npm i express
const express = require('express');

const app = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
    res.send(`
    <p>A demo for account recovery using authflow API. Click on the following link to try it</p>
    <a href="/recovery">Forgot password</a>
    `)

});

app.get('/recovery', async (req, res)=> {
    res.send("Test recovery");
});

app.listen(port, () => {
    console.log(`server started on port ${port}!`);
});
node app.js
app.get('/recovery', async (req, res)=> {
    const URLQuery = rawURLQuery(req.url);
    res.send(`
    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
            integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <title>Account recovery</title>
    </head>

    <body>
        <div class="container pt-4">
            <form class="" action="./recovery" method="POST" enctype="application/x-www-form-urlencoded">
                <div class="">
                    <label class="">
                        Phone number (include country code)
                    </label>
                    <input name="phone" id="phone" type="text" class="form-control mb-2" placeholder="Enter your phone number" />
                </div>
                <input type="hidden" name="state_token" value="${await initRecovery(URLQuery)}">
                <button type="submit" class="btn btn-primary">
                    Submit
                </button>
            </form>
        </div>
    </body>
    </html>
    `);
});
const port = process.env.PORT || 3000;
function rawURLQuery(url) {
    const index = url.indexOf('?');
    return (index === 0) ? url.substr(index + 1) : "";
}
npm i axios
const axios = require('axios');
const port = process.env.PORT || 3000;
const endpoint = "https://cube-crisp-110.authgear-staging.com";
async function initRecovery(url_query) {

    const url = `${endpoint}/api/v1/authentication_flows?${url_query}`;

    const input = {
        "type": "account_recovery",
        "name": "default"
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        startRecovery = await axios.post(url, input, {
            headers: headers
        });

        return startRecovery.data.result.state_token;
    }
    catch (error) {
        console.log(error.response.data.error);
        return error.response;
    }
}
{
    "result": {
        "state_token": "authflowstate_5QKK3BRPETYQ7SYWYFQ4N2MR3F0S8S0Q",
        "type": "account_recovery",
        "name": "default",
        "action": {
            "type": "identify",
            "data": {
                "options": [
                    {
                        "identification": "email"
                    },
                    {
                        "identification": "phone"
                    }
                ]
            }
        }
    }
}
async function beginRecovery(login_id, state_token) {

    const url = `${endpoint}/api/v1/authentication_flows/states/input`;

    const input = {
        "state_token": state_token,
        "batch_input": [
            {
                "identification": "phone",
                "login_id": login_id
            },
            {
                "index": 0 //option of the channel the recovery code will be sent to
            }
        ]
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        const recoveryIdentityStep = await axios.post(url, input, {
            headers: headers
        });

        return recoveryIdentityStep;
    }
    catch (error) {
        console.log(error.response.data.error);
        return error.response;
    }
}
app.use(express.urlencoded({ extended: true }));
app.post('/recovery', async (req, res) => {
    try {
        const apiResponse = await beginRecovery(req.body.phone, req.body.state_token);
        if (apiResponse.status == 200) {
            req.session.recovery_response = apiResponse.data.result.action.data;
            req.session.recovery_response.state_token = apiResponse.data.result.state_token;
            res.redirect("/verifyRecovery");
        } else {
            res.send("Error!")
        }
    }
    catch (error) {
        console.log(error)
        res.send("Error: authentication failed!");
    }
});
npm i express-session
const session = require('express-session');
const session = require('express-session');
app.get('/verifyRecovery', async (req, res) => {
    const recoveryResponseData = req.session.recovery_response;
    res.send(`
    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
            integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <title>Verify recovery code</title>
    </head>

    <body>
        <div class="container pt-4">
            <form class="" action="./verifyRecovery" method="POST" enctype="application/x-www-form-urlencoded">
                <div class="">
                <p>Email: ${recoveryResponseData.masked_display_name}</p>
                    <label class="">
                        Code
                    </label>
                    <input name="code" id="code" type="text" class="form-control mb-2" placeholder="Enter the Recovery code (000000 for this test) sent to the above email " />
                </div>
                <input type="hidden" name="state_token" value="${recoveryResponseData.state_token}">
                <button type="submit" class="btn btn-primary">
                    Verify
                </button>

                <div>
                    <a href="/resendOtp">Resend Code</a>
                    <span> (wait until ${recoveryResponseData.can_resend_at})</span>
                </div>
            </form>
        </div>
    </body>
    </html>
    `);
});
async function verifyRecoveryCode(code, state_token) {

    const url = `${endpoint}/api/v1/authentication_flows/states/input`;

    const input = {
        "state_token": state_token,
        "input": {
            "account_recovery_code": code
        }
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        const verifyCodeStep = await axios.post(url, input, {
            headers: headers
        });

        return verifyCodeStep;
    }
    catch (error) {
        return error.response;
    }
}
app.post('/verifyRecovery', async (req, res) => {
    try {
        const apiResponse = await verifyRecoveryCode(req.body.code, req.body.state_token);
        if (apiResponse.status == 200) {
            req.session.verify_step_state_token = apiResponse.data.result.state_token;
            res.redirect("/setPassword");
        } else {
            res.send("Error!")
        }
    }
    catch (error) {
        console.log(error)
        res.send("Error: authentication failed!");
    }
});
app.get('/setPassword', async (req, res) => {
    res.send(`
    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
            integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <title>Set new password</title>
    </head>

    <body>
        <div class="container pt-4">
            <form class="" action="./setPassword" method="POST" enctype="application/x-www-form-urlencoded">
                <div class="">
                <p>Set new password</p>
                </div>
                <div class="form-group">
                    <label>
                        New Password
                    </label>
                    <input name="password" type="password" class="form-control mb-2" placeholder="Enter your password" />
                </div>
                <div class="form-group">
                    <label>
                        Repeat Password
                    </label>
                    <input name="password2" type="password" class="form-control mb-2" placeholder="Enter your password" />
                </div>
                <input type="hidden" name="state_token" value="${req.session.verify_step_state_token}">
                <button type="submit" class="btn btn-primary">
                    Submit
                </button>
            </form>
        </div>
    </body>
    </html>
    `);
});
async function recoverySetPassword(password, state_token) {
    const url = `${endpoint}/api/v1/authentication_flows/states/input`;

    const input = {
        "state_token": state_token,
        "input": {
            "new_password": password
        }
    };

    const headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }

    try {
        const verifyCodeStep = await axios.post(url, input, {
            headers: headers
        });

        return verifyCodeStep;
    }
    catch (error) {
        console.log(error.response.data.error);
        return error.response;
    }
}
app.post('/setPassword', async (req, res) => {
    try {
        const apiResponse = await recoverySetPassword(req.body.password, req.body.state_token);
        if (apiResponse.status == 200 && apiResponse.data.result.action.data.finish_redirect_uri !== undefined) {
            //password reset complete, return control back to Authgear
            res.redirect(apiResponse.data.result.action.data.finish_redirect_uri);
        } else {
            res.send(apiResponse.data)
        }
    }
    catch (error) {
        console.log(error)
        res.send("Error: account recovery failed!");
    }
});
npm install express
npm install axios
const express = require('express');
const axios = require('axios');

const app = express();
const port = process.env.PORT || 3000;

const config = {
  client: {
    id: "CLIENT_ID",
    secret: "CLIENT_SECRET",
    redirect_url: "REDIRECT_URL"
  },
  auth: {
    tokenHost: "AUTHGEAR_ENDPOINT",
    tokenPath: '/oauth2/token',
    authorizePath: '/oauth2/authorize',
    scope: 'openid offline_access'
  },
};
app.get("/login", (req, res) => {

  const url = new URL(`${config.auth.tokenHost}${config.auth.authorizePath}`);
  url.searchParams.set('client_id', config.client.id);
  url.searchParams.set('redirect_uri', config.client.redirect_url);
  url.searchParams.set('response_type', 'code');
  url.searchParams.set('scope', config.auth.scope);

  if (req.query.source != null) {
    url.searchParams.set('state', req.query.source);
  }

  res.redirect(url);
  
});
http://localhost:3000/login?source=002
app.get("/", async (req, res) => {

  if (req.query.code != null) {
    const data = {
      client_id: config.client.id,
      client_secret: config.client.secret,
      code: req.query.code,
      grant_type: 'authorization_code',
      response_type: 'code',
      redirect_uri: config.client.redirect_url,
      scope: config.auth.scope
    };

    const sourceFromState = req.query.state;

    try {
      const getToken = await axios.post(`
        ${config.auth.tokenHost}${config.auth.tokenPath}`,
        data,
        {
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
        }
      );

      const accessToken = getToken.data.access_token;
      res.send(`
      <p>Access token: ${accessToken}, ${sourceFromState}</p>
    `);
    } catch (error) {
      res.send("An error occurred! Login could not complete. Error data: " + error);
    }
  }

  else {
    res.send(`
      <div style="max-width: 650px; margin: 16px auto; background-color: #EDEDED; padding: 16px;">
        <p>Hi there!</p>
        <p>This demo app shows you how to add user authentication to your Express app using Authgear</p>
          <p>Checkout <a href="https://docs.authgear.com">docs.authgear.com</a> to learn more about adding Authgear to your apps.</p>
        <a href="/login">Login</a>
      </div>
    `);
  }
});

app.listen(port, () => {
  console.log(`server started on port ${port}!`);
});
node app.js
import { EventOIDCJWTPreCreate, HookResponse } from "https://deno.land/x/authgear_deno_hook@v1.0.0/mod.ts";

export default async function(e: EventOIDCJWTPreCreate): Promise<HookResponse> {
  return {
    mutations:{
      jwt: {
        payload:{
          ...e.payload.jwt.payload,
          standard_attributes: e.payload.user.standard_attributes,
          custom_attributes: e.payload.user.custom_attributes
        }
      }
    },
    is_allowed: true
  };
}
https://<YOUR_AUTHGEAR_ENDPOINT>/oauth2/authorize?client_id={YOUR_CLIENT_ID}&response_type=code&scope=openid
curl --request POST \
  --url 'https://<YOUR_AUTHGEAR_ENDPOINT>/oauth2/token' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=authorization_code \
  --data code={YOUR_AUTHORIZATION_CODE} \
  --data redirect_uri={YOUR_REDIRECT_URI} \
  --data 'client_id={YOUR_CLIENT_ID}' \
  --data client_secret={YOUR_CLIENT_SECRET} \
  --data scope=openid

Monitor

Monitor your Authgear implementation

You can monitor the Authgear app, and see and retrieve log event data.

Node.js
here
http://localhost:3000/
OAuth 2.0 framework
Express
User Profiles
Hooks
fields in the JWT Access Tokens by default
add custom attributes
User Profiles
create it for free
registered application
Authgear account
Events
Deno
Typescript library
Standard Attributes
Custom Attributes
decoding the JWT token
JWT Debugger tool

Audit Log for Admin API and Portal

The Admin API & Portal tab in the Audit Log page allows you to analyze and monitor changes and activities that occur on Admin API and the Authgear Portal of your project.

The data under this tab can be handy for securing your Authgear project. For example, whenever an admin on your project downloads the Admin API key, the event is registered under the Admin API & Portal tab.

Accessing Admin API & Portal Audit Through the Admin API.

Activity logs for Admin API and Portal are part of the data the auditLogs query returns.

For example, the following query will return any recent events from Admin API and Portal that have been logged:

query {
  auditLogs(first:5){
    edges{
      node{
        activityType
        clientID
        createdAt
        data
      }
    }
  }
}

Note: The above request will also include events triggered by users.

Log Events

The following is a list of the activity types that are logged:

Project Actions

Activity type
Description

PROJECT_APP_SECRET_VIEWED

An admin downloaded the Admin API key

PROJECT_APP_UPDATED

Project configurations updated

PROJECT_BILLING_CHECKOUT_CREATED

An admin attempted to subscribe to one of the billing plans

PROJECT_BILLING_SUBSCRIPTION_CANCELLED

Billing subscription was canceled

PROJECT_BILLING_SUBSCRIPTION_STATUS_UPDATED

Account billing status is updated

PROJECT_BILLING_SUBSCRIPTION_UPDATED

Billing details updated

PROJECT_COLLABORATOR_DELETED

An admin is removed

PROJECT_COLLABORATOR_INVITATION_ACCEPTED

A user accepted an invitation to become an admin

PROJECT_COLLABORATOR_INVITATION_CREATED

Invitation to add new admin sent

PROJECT_COLLABORATOR_INVITATION_DELETED

A previously sent admin invitation was canceled

PROJECT_DOMAIN_CREATED

A new custom domain name added

PROJECT_DOMAIN_DELETED

A custom domain name was removed

PROJECT_DOMAIN_VERIFIED

A domain name was successfully verified

User Mutations

Activity type
Description

ADMIN_API_MUTATION_SET_DISABLED_STATUS_EXECUTED

Admin disabled/enabled a user account

ADMIN_API_MUTATION_CREATE_SESSION_EXECUTED

A new session is created

ADMIN_API_MUTATION_ANONYMIZE_USER_EXECUTED

An admin initiated the process to annonymize a normal user. This command will delete all user data like email, full name and phone number

ADMIN_API_MUTATION_CREATE_IDENTITY_EXECUTED

New Identity was created by an admin

ADMIN_API_MUTATION_CREATE_USER_EXECUTED

An admin created a new user

ADMIN_API_MUTATION_DELETE_AUTHENTICATOR_EXECUTED

An authenticator was removed

ADMIN_API_MUTATION_DELETE_AUTHORIZATION_EXECUTED

An authorization was removed

ADMIN_API_MUTATION_DELETE_IDENTITY_EXECUTED

Identity deleted

ADMIN_API_MUTATION_DELETE_USER_EXECUTED

An admin deleted a user

ADMIN_API_MUTATION_GENERATE_OOB_OTP_CODE_EXECUTED

New OTP code generated

ADMIN_API_MUTATION_RESET_PASSWORD_EXECUTED

Password was reset by an admin

ADMIN_API_MUTATION_REVOKE_ALL_SESSIONS_EXECUTED

All sessions revoked

ADMIN_API_MUTATION_REVOKE_SESSION_EXECUTED

A users session is revoked

ADMIN_API_MUTATION_SCHEDULE_ACCOUNT_ANONYMIZATION_EXECUTED

An admin scheduled the anonymization of a user account

ADMIN_API_MUTATION_SCHEDULE_ACCOUNT_DELETION_EXECUTED

An admin scheduled the deletion of a user

ADMIN_API_MUTATION_SEND_RESET_PASSWORD_MESSAGE_EXECUTED

Password reset message was sent

ADMIN_API_MUTATION_SET_VERIFIED_STATUS_EXECUTED

Verified status for a user is updated

ADMIN_API_MUTATION_UNSCHEDULE_ACCOUNT_ANONYMIZATION_EXECUTED

A previously scheduled user anonymization request was canceled

ADMIN_API_MUTATION_UNSCHEDULE_ACCOUNT_DELETION_EXECUTED

A previously scheduled user deletion request was canceled

ADMIN_API_MUTATION_UPDATE_IDENTITY_EXECUTED

Identity updated by admin

ADMIN_API_MUTATION_UPDATE_USER_EXECUTED

An admin updated details like a user's name, gender and more

Custom Email Provider

Optimize for email deliverability by using your own SMTP server to send Authgear Emails (such as forgot password, verifications) in your own domains.

To send Authgear emails to end-users with your own domain, e.g. support@myapp.com. You will need to configure the external SMTP provider.

Authgear currently supports SendGrid and other custom SMTP Providers.

Send from an email address under your domain

The sender address can be configured by changing the value of theemail.default.sender key in the localization JSON. Go to Portal > Branding > Custom Text and add/change the value of email.default.sender to your own email address, for example no-replay@myapp.com, and Save the settings. The value can be set separately for each locale.

Sender domain authentication

Before adding the email service provider to Authgear, make sure the sender domain is verified and authenticated on the email service. For example, your domain myapp.com should be configured in your SendGrid account so Authgear can use the account to send emails with no-reply@myapp.com.

Follow the instructions from the email service provider for setting up your domain:

Configure the external SMTP provider

The external SMTP provider can be set up in Portal > Advanced > Custom Email Provider. Enable the Use my own provider toggle to see the fields.

Use SendGrid as external SMTP provider

  1. Log in to your SendGrid account

  2. Create API Key in Settings > API Keys

  3. Set the API Key Name for your reference the choose Restricted Access under API Key Permissions

  4. Under Access Details, expand Mail Send and give Full Access to the Mail Send permission

  5. Click Create & View. Copy the API key created and save it somewhere safe

  6. In Authgear Portal, navigate to Custom Email Provider

  7. Enable Use my own provider.

  8. Choose SendGrid and paste the API key you copied, and Save

  9. You can send a test email to check the configuration

Using other SMTP Providers

Other SMTP providers can be set manually by providing the Host, Port, Username, and Password. They can be obtained from the documentation or instructions from your email service provider.

Custom domain

Set up a custom domain to let your users access the Authgear pages with your unique, brand-centric domain name. You can use a custom domain (e.g. auth.yourdomain.com) instead of the Authgear generated domain (e.g. <YOUR_APP>.authgear.cloud).

A paid subscription is required for setting up a custom domain.

How to Set Up a Custom Domain

1. Add domain

  • Go to Branding > Custom Domains in your project portal.

  • Enter the custom domain name that you would like to connect to Authgear, and click Add.

  • Your custom domain will appear on the list, click Verify to start the verification process.

2. Verify domain ownership

  • Go to your domain provider's site, and add DNS records based on the values shown on the portal page.

  • Click Verify after adding the DNS records, you may need to wait for the propagation of your updated DNS records.

3. Activate your custom domain

  • You will return to the custom domain list after verifying your custom domain. Click Activate to use your custom domain.

  • Now you can access Authgear pages with your custom domain, your default Authgear generated domain (e.g. <YOUR_APP>.authgear.cloud) cannot be used anymore. Update your SDK endpoint to use the new custom domain.

  • The certificate of your custom domain is managed by Authgear, you may need to wait for a while for certificate provisioning.

Configure Post-login link and Post-logout link

Users can access the login and logout pages directly in your Authgear project when you're using a custom domain. As a result, the post-login and post-logout links are available to help you determine where users are redirected when they access the above pages without an OAuth flow.

To configure these values, in Authgear Portal navigate to Branding > Custom Domains. Then scroll down to the Default Redirect URLs section.

Post-login link

Use this field to set the page where users will be redirected after login if they visit the login page directly instead of going through an OAuth flow.

Post-logout link

The URL you enter as a post-logout link is where users will be redirected after logout when they visit the logout page directly.

Audit Log For Users Activities

Authgear provides the event logs for you to analyze security issues and monitor the business.

View and retrieve logs

View in Portal

The portal provides an interface for you to look up the log by event and date range.

The Users Activities tab on the Audit Log page filters the log to only show activities performed by a normal user or by an admin on a user's profile.

Retrieve with Admin API

query {
  auditLogs(first:5){
    edges{
      node{
        activityType
        clientID
        createdAt
        data
      }
    }
  }
}

Filtering Audit Log

When using the Admin API, you can filter the Audit Log by an attribute like activityTypes to omit records you're not interested in.

The following is an example that includes filters.

query {
  auditLogs(first:5, activityTypes:[USER_AUTHENTICATED,USER_DELETED]){
    edges{
      node{
        activityType
        clientID
        createdAt
        data
      }
    }
  }
}

The above query will only return events with activity types USER_AUTHENTICATED and USER_DELETED.

Log events

Here is the list of activity types that are logged:

Authentication failed

Activity type
Description

AUTHENTICATION_IDENTITY_ANONYMOUS_FAILED

Anonymous user authentication failed

AUTHENTICATION_IDENTITY_BIOMETRIC_FAILED

Authentication with biometric failed

AUTHENTICATION_IDENTITY_LOGIN_ID_FAILED

A user's login attempt failed because the email or user ID provided is not found

AUTHENTICATION_PRIMARY_OOB_OTP_EMAIL_FAILED

Authentication using the OTP sent via email failed

AUTHENTICATION_PRIMARY_OOB_OTP_SMS_FAILED

Authentication using the OTP sent via SMS failed

AUTHENTICATION_PRIMARY_PASSWORD_FAILED

A user entered an invalid password during a login attempt

AUTHENTICATION_SECONDARY_OOB_OTP_EMAIL_FAILED

2FA via email failed

AUTHENTICATION_SECONDARY_OOB_OTP_SMS_FAILED

2FA via SMS failed

AUTHENTICATION_SECONDARY_PASSWORD_FAILED

Secondary authentication using password failed

AUTHENTICATION_SECONDARY_RECOVERY_CODE_FAILED

Recovery code verification failed

AUTHENTICATION_SECONDARY_TOTP_FAILED

A 2FA attempt failed

Identity changes

Activity type
Description

IDENTITY_BIOMETRIC_DISABLED

Biometric login is disabled by a user or an admin

IDENTITY_BIOMETRIC_ENABLED

User enabled biometric login

IDENTITY_EMAIL_ADDED

A user or admin added a new email to an existing user

IDENTITY_EMAIL_REMOVED

An email address was removed from an existing user's profile

IDENTITY_EMAIL_UPDATED

A user updated their email address

IDENTITY_OAUTH_CONNECTED

A profile is linked to OAuth

IDENTITY_OAUTH_DISCONNECTED

A profile is unlinked from OAuth

IDENTITY_PHONE_ADDED

A user or admin added a new phone number to an existing user

IDENTITY_PHONE_REMOVED

A phone number was removed from an existing user's profile

IDENTITY_PHONE_UPDATED

A user updated their phone number

IDENTITY_USERNAME_ADDED

A user or admin added a new username to an existing user

IDENTITY_USERNAME_REMOVED

A user or admin removed the username for a user

IDENTITY_USERNAME_UPDATED

The username for a user was updated

User actions

Activity type
Description

USER_ANONYMOUS_PROMOTED

This event is triggered when an anonymous user is promoted to a normal user

USER_AUTHENTICATED

Successful user sign-in

USER_CREATED

A new user successfully registered

USER_DELETED

A user account is deleted

USER_DELETION_SCHEDULED

A user account deletion is scheduled

USER_DELETION_UNSCHEDULED

A previously scheduled user deletion is unscheduled

USER_DISABLED

User account disabled. An admin disabling a users account can trigger this event

USER_PROFILE_UPDATED

A user updated details like their profile name, gender and more

USER_REENABLED

A user account that was previously disabled is enabled

USER_SESSION_TERMINATED

An active user session is terminated

USER_SIGNED_OUT

A user that was signed in logged out

Others

Activity type
Description

WHATSAPP_OTP_VERIFIED

User completed a verification process using WhatsApp to receive OTP

SMS_SENT

An SMS notification like OTP was sent to a user

EMAIL_SENT

An email notice like verification code was sent to a user

Log data

Each audit log event contains the following attributes in their data

Attribute
Description

id

Unique identifier of the event

seq

Sequence number of the event

type

Activity type

context

The who, when and where of the event triggered. e.g. IP address, user agent, user ID, timestamp

payload

Relevant data according to the event type:

Messaging (SMS, Email OTP): the phone number/email address of the receiver

Authentication/Identity/User actions: a snapshot of the related session and user attributes

User Analytics by Google Tag Manager

Learn how to integrate popular analytics and tracking tools into your Authgear project using Google Tag Manager

Authgear allows you to add third-party user analytics tools to your project using Google Tag Manager.

What is Google Tag Manager?

Google Tag Manager (GTM) is a tag management tool from Google that makes it easy to add marketing tags to your website without modifying the site's source code.

Tags can help you track traffic and user behavior on your website or application.

In this guide, we will show you how to add Google Tag Manager to your Authgear project and send data to Google Analytics. You can also configure Google Tag Manager to send data from your Authgear project to other marketing tags from providers like Facebook.

Pre-requisites

In order to setup Google Tag Manager and Google Analytics with Authgear, you need to have the following:

  1. Authgear account

  2. Google Tag Manager Account

  3. Google Analytics Account

Part 1: Connect Google Tag Manager to Authgear project

The process for connecting your GTM account to Authgear is simple and can be done in these two steps.

Step 1: Get GTM container ID

Google Tag Manager lets you create containers that hold marketing tags. Each container has a unique ID and you'll need this container ID to connect your GTM container to Authgear.

If you don't have a container for your Authgear project yet, click on Create Account to create a new container. Enter your domain name for your Authgear project as the container name and select a target platform. For this example, we'll select Web as the target platform.

Step 2: Add GTM container ID to Authgear

First, log in to the Authgear Portal, then select your project and navigate to Integrations.

Click on the Connect button next to the Google Tag Manager addon to open the configuration page.

Paste the GTM container ID you got from the previous step then click the Save button. And with that, you've successfully connected your GTM container to Authgear. In the next steps, we'll show you how to create tracking tags and send data to Google Analytics.

Part 2: Track traffic and send data to Google Analytics

Google Analytics is one of the marketing tags we can manage from GTM. In this part of the guide, we'll set up some tags to track page views and user events like clicking on a link or button. The tags will send these data to Google Analytics.

Step 1: Set up Google Analytics data stream

In order to create tags that send data to Google Analytics, you need to have an active data stream on Google Analytics. GTM requires the details for this stream while creating new tags for Google Analytics.

To create a stream, log in to Google Analytics then navigate to the Admin settings page.

Create a new Google Analytics property for your Authgear project or select an existing one. Click on the Data Streams item under the property to view all streams and add a new web stream for your Authgear project.

Note down the Measurement ID for your stream as we'll be using it later to create new tags.

Step 2: Create a new user-defined variable in GTM

Before we start sending data to Google Analytics, let's create a new variable in Google Tag Manager.

Go back to GTM and select the correct container for your project.

Next, click on the Variables item on the left side navigation bar and create a new user variable with the following details:

  • Variable type: Data Layer Variable

  • Data Layer Variable Name: gtm.element.dataset.authgearEvent

Once you're done save the variable as "gtm.element.dataset.authgearEvent" and continue to the next step.

Step 3: Create a click Trigger

Navigate to Triggers from the sidebar and create a new trigger with the following details:

  • Trigger type: Click > All Elements

  • This trigger fires on: Some Clicks

Authgear's implementation of GTM is declarative. The primary button on each page has data-authgear-event attribute. We'll be setting a condition for the "Some Clicks" using that attribute. Configure Some "Click" as shown below:

Next, save the trigger as "Authgear-btn-click" and continue.

Step 4: Create Page View Tag

Navigate to Tags from the sidebar and create a new tag with the following configurations:

  • Tag type: Google Analytics > Google Tag

  • Tag ID: <Your Tag ID is the unique Measurement ID for your stream in Google Analytics (See part 2 step 1 for more details)>

Next, expand the Advanced Settings section and set Tag firing options to Once per page.

Now, scroll down to the Trigger section of the new tag and select All Pages (page view) as the trigger.

Save this new tag as "Auth-gear-pageview" and continue.

Step 5: Create Event Tag

In this step, create another tag with the following configuration:

  • Tag type: Google Analytics > Google Analytics: GA4 Event

  • Measurement ID: <Your Google Analytics stream measurement ID>

  • Event Name: gtm.element.dataset.authgearEvent

Next, set the trigger for this tag to the "Authgear-btn-click" trigger we created earlier.

Save the tag as "Authgear-event-tag" and continue to preview the entire setup or publish to go live.

Conclusion

After you publish your changes in Google Tag Manager when users generate hits or click buttons with the data-authgear-event attribute on your project you should see data on Google Analytics.

The following is a list of values for the data-authgear-event attribute:

  • authgear.button.change_password

  • authgear.button.change_additional_password

  • authgear.button.create_password

  • authgear.button.change_login_id

  • authgear.button.remove_login_id

  • authgear.button.resend_oob_otp

  • authgear.button.enter_oob_otp

  • authgear.button.enter_password

  • authgear.button.enter_recovery_code

  • authgear.button.enter_totp

  • authgear.button.send_reset_password_code

  • authgear.button.sign_in

  • authgear.button.sign_up

  • authgear.button.sign_out

  • authgear.button.oauth

  • authgear.button.reset_password

  • authgear.button.continue_with_current_account

  • authgear.button.use_another_account

  • authgear.button.remove_biometric

  • authgear.button.schedule_account_deletion

  • authgear.button.connect_oauth

  • authgear.button.disconnect_oauth

  • authgear.button.resend_verification_code

  • authgear.button.update_profile

  • authgear.button.regenerate_recovery_code

  • authgear.button.download_recovery_code

  • authgear.button.remove_totp

  • authgear.button.remove_oob_otp

  • authgear.button.setup_oob_otp

  • authgear.button.setup_totp

  • authgear.button.enter_verification_code

  • authgear.button.revoke_session

  • authgear.button.revoke_session_group

  • authgear.button.revoke_all_sessions

Analytics

See information about the total number users and active users on your Authgear project

The Analytics section on the Authgear portal provides reports on your project activities. For example, the report shows the total number of users that sign up and active users over a specific time interval.

In this guide, you'll get detailed information about the information provided on the Authgear Analytics page and how to interpret it.

Activity

The Analytics page shows two activity bar charts that show a weekly or monthly summary of user activities on your Authgear project.

Active user

The first chart shows the total active users per week or month. Active users are users who sign up, log in, or access their accounts within a specific time.

Total users

The second bar chat in the Activities section shows the total number of users your Authgear project has over a specific time interval. That is the total number of accounts created minus deleted users.

Signup Conversion

The signup conversion piechart shows how many users visited your signup page (unique pageviews) and how many went ahead to complete the signup process. This report also shows a percentage of the signup conversion (unique pageviews vs. total signups).

User Signup Methods

This section shows how many users you have per signup method in a pie chart.

Note: The data on the Analytics page may take 24 hours to be updated.

Account Deletion

Allow end-users to initiate account deletion within the apps.

Show "Delete Account" button in User Settings

Enable this button in the Advanced -> Account Deletion page in the Portal

Note that if you enable this feature, you have to prepare for encountering invalid session every time your users close User Settings in your mobile apps. If your users unfortunately decided to delete their account in User Settings, all their sessions will become invalid immediately.

You must verify the validity of the session every time the User Settings is closed. The open method in the SDK is blocking. You can verify if the user session is still valid when the method resolves. Here is an example with the React Native SDK:

Open Account Deletion Page From Authgear SDK

You can now open the account deletion directly from Authgear SDKs. The account deletion page will be opened in a WebView.

The following code examples show how to open the account deletion page from Authgear SDKs:

Deactivated User

When the end-user has initiated the account deletion, their account will be deactivated and scheduled for deletion after the grace period.

Deactivated users are always disabled. They will not be able to complete the authentication process. The is_deactivated status signal that the is_disabled status was turned true by the end-user themselves rather than the admin.

Schedule Deletion

You can set the grace period for how long the user account will be deactivated before deleted from the system. The default value is 30 days, you can choose between 1 to 180 days.

Initiate Deletion from the Portal

An end-user account can also be deleted using the Portal. In the User Management page, click the Remove User button to remove them immediately or schedule the deletion.

Initiate Deletion from Admin API

Alternatively, if you did not enable the "Delete Account" button in User Settings, you can implement the button in your app by yourself. You can schedule a deletion or delete immediately.

Schedule Deletion

Here is an example:

GraphQL

Immediate Deletion

Here is an example:

GraphQL

Webhook events

You may listen to the following events to integrate the deletion behavior to your apps.

Non-blocking events

  • user.disabled

  • user.reenabled

  • user.deletion_scheduled

  • user.deletion_unscheduled

  • user.deleted

Blocking event

  • user.pre_schedule_deletion

Manage Users Roles and Groups

Define and manage roles and groups that you can apply to your users

1.0 Introduction

The following case is an example of how you can use roles to deliver unique features and interfaces to different categories of users of your application. Let's say you have an application XYZ that powers a transportation business. The app has roles for admin, driver and passenger. You can use the value Authgear returns in UserInfo or JWT access token to enable features for managing drivers to a user with admin role only. Similarly, you can allow only users with driver role view features to manage their vehicle, passengers, and trip. Finally, you can restrict users with the passenger role to only view their ticket and trip details.

In this post, you'll learn how to create roles and groups for your Authgear project and how to manage them.

You can create a group in your Authgear project and add one or more roles to the group. Both groups and roles can be applied to a user. For instance, if your Authgear project, has the following roles:

  • management

  • department_lead

  • team_member

And a managers group, you can add the management and department_lead roles to the group. Then, adding a user to the managers group will grant them both management and department_lead roles.

The following figure shows the core relationship with Groups, Roles, and Users in Authgear.

1.1 Properties of Roles and Groups

Each role or group has three properties that describe it. These include a required key, and optional name and description.

1. Role/Group Key

The key property serves as the identifier for the role or group. The value for key is what AUthgear will include in the UserInfo and JWT access token of a user. A valid key must meet the following conditions:

  • The value of key can not be empty.

  • A key must be between 1 and 40 characters long.

  • The valid characters are [a-zA-Z0-9:_].

  • The prefix authgear: is reserved for Authgear internal use.

The following are some examples of valid keys:

  • reader

  • app:editor

  • store_manager

2. Name

Name is an optional label for a role or group. The value for the name property is what will be displayed in Authgear portal. It has less strict constrict for allowed characters. For example, you can use white spaces here.

3. Description

The description property is also optional. You can use it to give more details about a role or group.

In the next section of this post, we'll show you how to create roles and groups for your project.

1.2 Example of Role in UserInfo Endpoint Response

The. following JSON document shows how roles are returned when your application requests for UserInfo:

The value of the https://authgear.com/claims/user/roles attribute is an array that contains the roles of the current user.

2.0 How to Create a New Role

2.1 Creating Roles from the Authgear Portal

Follow these steps to create new roles in your Authgear project via the Portal.

Step 1

First, log in to Authgear Portal, select your project then navigate to User Management > Roles to open the Roles page.

Step 2

Click the Create Role button in the middle of the Roles page (or the top right corner if you have existing roles) to start creating a new role.

Enter the Name, Role Key, and Description of your new role in their respective fields. Click on the Create button at the bottom of the form to finish creating your new role.

Repeat the above steps to add more roles.

2.2 Creating Roles using the Admin API

As mentioned earlier in this post, you can also create new roles using the Admin API. In this section, we'll walk you through the steps for doing that.

Step 1

Step 2

Run the following mutation to create a new role:

3.0 How to Create a New Group

Just like roles, you are responsible for creating groups for your Authgear project. You can also create new groups either via Authgear Portal or using the Admin API.

3.1 Creating Groups from the Authgear Portal

The steps for creating a new group from the Portal are similar to that of roles. The steps are as follows:

Step 1

First, log in to Authgear Portal, select your project then navigate to User Management > Groups to open the Groups page.

Step 2

Click the Create Group button in the middle of the screen (or in the top right corner if you already have some groups) to access the Create Group form.

Enter the Name, Group Key and Description in the group creation form then click the Create button to finish.

3.2 Creating Groups using the Admin API

It's possible to create a new group using the Admin API GraphQL. The following guide shows the steps for doing that.

Step 1

Step 2

Execute the following GraphQL mutation to create a new group:

4.0 Managing Existing Roles

You can manage the roles you've created via the Portal or using the Admin API. In this section, we'll cover how to manage roles.

4.1 Add Role to a User

To add a role to a user, first, in the Authgear Portal, navigate to User Management > Users. From this page, you can view a list of all the users who have signed up on your Authgear project. You can also search users by their current roles there.

Next, click on the user you wish to add a new role to. This will open their User Details page. From that page, navigate to the Roles tab

To remove an existing role from a user, click on the Remove button next to the role in the user's Roles tab.

4.2 Add Group to Role

Adding a group to a role is a way of connecting a role and a group from the role management side.

To do this in Authgear Portal, first navigate to User Management > Roles, then click on the role you wish add a group to.

Next, in the details page for the selected role, go to the Groups tab, then click the Add to Group button. Select the group you wish to add from the drop-down then click Add. If there's no groups in the dropdown, try creating some new groups first.

4.3 Update or Delete a Role

To update the properties of an existing role such as the name, description or key, navigate to User User Management > Roles in Authgear Portal. Click on the role you wish to modify to open the Settings tab, then change the value for the property you wish to update in the form. Once you're done, click on the Save button.

To delete a role, click on the Delete button once you open the role's Settings tab.

5.0 Managing Existing Rules

5.1 Add Group to User

To add a group to a user's profile in the Portal, first navigate to User Management > Users and select a user.

In the User Details page, switch to the Groups tab then click on Add to Group.

Select the group you wish to add the user to from the drop-down then click on Add.

5.2 Add Role to Group

To add a role to a group, navigate to User Management > Groups then click on the group you wish to add roles to.

In the group details page, switch to the Roles tab, then click on the Add Role button.

Select the roles you wish to add to the group from the drop-down then click on the Add button.

5.3 Update or Delete Group

To update an existing group, go to User Management > Groups and click on the group you wish to update. Modify the property you wish to update using the form in the group's Setting tab. Once you're done, click on Save to keep your changes.

To delete an existing group, click on the Delete Group button once you're in the Settings tab for that group.

Import Users using User Import API

Use the user import API to bulk import users from external systems to your Authgear project

Some ways to add users to your Authgear project include; using the Add User UI in Authgear Portal, using the createUser() mutation in Admin API, and last but not least, having the user accounts created using sign-up page on AuthUI.

A common downside of all the above-listed methods is that they do not support batch import of users. Meaning, that you have to add users one by one. This isn't ideal for importing multiple users from existing legacy systems to Authgear. For adding bulk users, there is the User Import API.

In this post, you'll learn what the User Import API is and see examples of how to import bulk users to an Authgear project.

User Import API

Endpoints

The following are the endpoints for the User Import API.

Initiate Import

Use this endpoint to start a new user import task.

Check Status

Use this endpoint to verify the status of an existing user import task.

Usage Example

In this section, you can find code for a simple example of using the User Import API to add multiple users to an Authgear project.

Pre-requisites

To follow this example and be able to run the code on your local machine, you must have the following:

  • Install Express.js by running the following command from your project directory: npm install express.

Step 1: Get Admin API JWT

As mentioned earlier in this post, the User Import API requires the Admin API JWT to access. In this step, we'll generate an Admin API JWT using Node.js.

First, install JsonWebToken (a Node package for generating JWT) by running the following command:

The following code shows how to get the token:

Step 2: Import Users from a JSON Document

To import users to your Authgear project using the User Import API, make a POST HTTP(S) request to the Initiate Import endpoint (/_api/admin/users/import).

In the following steps, we'll use the node-fetch package to make HTTP requests to the User Import API. Hence, install node-fetch by running the following command:

The following code sample demonstrates how to import 2 users from a JSON document that's stored in a simple constant (const data):

If the user import was initiated successfully, you'll get a response that looks like this:

In the next step, we'll use the value of the id field from the above response to query the status of the import task.

Step 3: Get the Status of the Import Task

In this step, we'll make a GET HTTP(S) request to the Check Status endpoint (/_api/admin/users/import/{ID}) to get the status of the user import task we initiated in the last step. You'll need to replace {ID} in the URL with the value of id in the previous response.

To do this, add a new route to the Express app that accepts the task id as a parameter and uses that id to query the status of the task. Here's the code for the route:

The response to the request to query the status of the import task will look like this:

From the response, you can see the status of the entire task (import was completed), including a summary ( { "total": 2, "inserted": 2, "updated": 0, "skipped": 0, "failed": 0 } ).

The details field contains an array of details such as the outcome for each user in the original JSON document.

Export Users using the User Export API

Export users from your project into a CSV or JSON file

In this guide, you'll learn how to use the User Export API.

User Export API

The User Export API allows developers to bulk export users into a file.

The export process is asynchronous. That is, the process runs in the background. Hence, you will need to initiate an export task in one endpoint call and then, make an additional call to another endpoint to get the status of the export task.

The following are the two endpoints for the User Export API:

Initiate Export Task

POST /_api/admin/users/export

Use this endpoint to create a new user export task.

Headers

Body

The Initiate Export endpoint accepts JSON input via an HTTP(S) request body. The following is an example of the input:

  • The format field is where you specify the format of the export file. The value can be csv or ndjson.

  • csv: use this field when format is set to csv. The value is an object with a fields property.

  • csv.fields: you can use this field to list all the user attributes you want to include as fields in the CSV file. The value should be an array and each item in the array is an object with a pointer and an optional field_name property that describe a user attribute.

Check Status

GET /_api/admin/users/export/{Task ID}

Use this endpoint to query the status of an existing export task. Replace {Task ID} with the task id returned in the response body of the initiate export endpoint.

Headers

Example: Using the User Export API

The following example shows how to use the User Export API in a Node.js application.

Step 1: Get Admin API JWT

First, you need to get the Admin API JWT that will be used to authenticate requests to the endpoints.

To do that, install JsonWebToken (a Node package for generating JWT) by running the following command:

Now, create a generateJWT() function in your Express app to generate the JWT:

Step 2: Initiate User Export Task

Make an HTTP(S) POST request to the initiate export endpoint to initiate a new user export task.

To do that, first, install the node-fetch package in your app using this command:

Then add the following code to your application:

The response to the HTTP(S) request in this step should look like this:

Response

  • id: the value of id is the task ID that can be used in the check status endpoint to query the task and get the download URL for the export file.

Step 3: Check the Status of a User Export Task

In this step, we'll check the status of the export task we initiated by making an HTTP(S) request to the Check Status endpoint (/_api/admin/users/export/{Task ID}). Replace {Task ID} in the URL with the task ID for the export task in the previous task.

Add the following route to your app to check the status of an export task using the task ID:

When the status task is completed, the HTTP(S) response body will look like this:

Response

  • download_url : open the URL in the value of download_url to download the exported users file.

Note: The result from a completed export task will expire after 24 hours. Hence, after 24 hours, you can no longer use the task ID associated with the task to generate a new download link.

Setup DNS records and verify

You can view the audit log in the Portal, or retrieve logs using the .

The API schema can be found in the . For example:

To get the container ID, log in to and navigate to the dashboard's homepage. You should find a list of all your containers and their ID. Note down the ID for the container you wish to connect to Authgear.

In Oct 2021, that all apps allowing users to create accounts should also provide ways for them to initiate account deletion within the apps, starting from January 31, 2022. It is also a good design to give your end-users more control over their data.

On Jan 22, 2022 to extend the deadline to June 30 2022.

In the pre-built page, you can show a button for the end-users to initiate account deletion.

Your backend server can invoke the mutation scheduleAccountDeletion with the to initiate the account deletion.

Your backend server can invoke the mutation scheduleAccountDeletion with the to initiate the account deletion.

See the event details in .

Roles and Groups can extend access management on your application that Authgear powers. Authgear includes a user's roles in the response from the and in the JWT access token.

It is up to you to create roles for your Authgear project based on your unique need and use case. You can create new roles using the Authgear Portal or the (using GraphQL).

Set up your custom code with the GraphQL endpoint. Or use the GraphiQL Explorer provided by Authgear (Navigate to Advanced > Admin API > GraphiQL Explorer in Authgear Portal to access).

Implement your own custom code that has . Alternatively, you can use the GraphiQL Explorer in Authgear Portal (Navigate to Advanced > Admin API > GraphiQL Explorer).

Then, click the Add Roles button, select a role from the drop-down menu, and click Add. If the drop-down is empty, it is possible that you have not created any roles yet. See .

The User Import API is an API that supports the bulk import of users from another system to an Authgear project. This API is not part of the Admin API GraphQL. However, a valid is required to access the endpoints of the User Import API.

To learn more detailed information about the User Import API (such as endpoints, inputs, and responses), see the .

An Authgear account. Sign up for free .

installation on your local computer.

See our post on for a more detailed guide (and examples for other programming languages/frameworks) on how to get your key ID, and private key and generate Admin API JWT.

The user data you wish to import must be provided as a JSON input in the HTTP(S) request body as specified in the .

The Export User API offers a means for exporting user data such as user ID, email, phone number, etc from your Authgear project into a or file.

To make HTTP(S) requests to Export User API endpoints, your application must be authenticated using an in the Bearer Authorization header. The API will return a "403 Forbidden" error if an invalid JWT is used.

Name
Value
Name
Value

See the for more details about the endpoints, inputs, and pointers.

See for a more detailed guide on how to get your key ID, and private key and generate Admin API JWT using different programming languages.

How to set up domain authentication on SendGrid
Admin API
GTM
// This method blocks until the user closes User Settings.
await authgear.open(Page.Settings);
// One way to verify the validity of the session is to get User Info once.
await authgear.fetchUserInfo();
// This method blocks until the user closes User Settings.
await authgear.open(SettingsPage.settings);
// One way to verify the validity of the session is to get User Info once.
await authgear.getUserInfo();
// This method blocks until the user closes User Settings.
await authgear.OpenAsync(SettingsPage.Settings);
// One way to verify the validity of the session is to get User Info once.
await authgear.FetchUserInfoAsync();
authgear
  .deleteAccount({
    redirectURI: "<POST_DELETE_REDIRECT_URI>",
    colorScheme: colorScheme as ColorScheme,
  })
_authgear.deleteAccount(
        redirectURI: "<POST_DELETE_REDIRECT_URI>",
      );
SettingsActionOptions options = new SettingsActionOptions(
        "<AUTHGEAR_REDIRECT_URI>"
);
options.setColorScheme(getColorScheme());
mAuthgear.deleteAccount(options, new OnOpenSettingsActionListener() {
    @Override
    public void onFinished() {
        mIsLoading.setValue(false);
        Log.d(TAG, "deleteAccount finished");
    }

    @Override
    public void onFailed(Throwable throwable) {
        Log.d(TAG, throwable.toString());
        mIsLoading.setValue(false);
        setError(throwable);
    }
});
authgear?.deleteAccount(
    colorScheme: self.colorScheme,
    redirectURI: "<AUTHGEAR_REDIRECT_URI>"
) { result in
    switch result {
    case .success:
        self.successAlertMessage = "Deleted account successfully"
    case let .failure(error):
        self.setError(error)
    }
}
mutation {
  scheduleAccountDeletion(input: {
    userID: "USER_ID"
  }) {
    user {
      id
      isDisabled
      isDeactivated
      disableReason
      deleteAt
    }
  }
}
mutation {
  deleteUser(input: {
    userID: "USER_ID"
  }) {
    deletedUserID
}
{
  "custom_attributes": [],
  "email": "user@example.com",
  "email_verified": true,
  "family_name": "John",
  "gender": "male",
  "given_name": "Doe",
  "https://authgear.com/claims/user/can_reauthenticate": true,
  "https://authgear.com/claims/user/is_anonymous": false,
  "https://authgear.com/claims/user/is_verified": true,
  "https://authgear.com/claims/user/roles": [
    "department_lead",
    "team_member"
  ],
  "sub": "e3079029-f230-4c24-91c1-c2cd63a6a4af",
  "updated_at": 1694947082,
  "x_web3": {
    "accounts": []
  }
}
mutation {
  createRole(input: { key:"department_lead", name:"Team Lead", description: "Role for a leader of a specific department" }) {
    role {
      id
      key
    }
  }
}
{
  "data": {
    "createRole": {
      "role": {
        "id": "Um9sZTozNDM5MWQ1Ni00OTEwLTQ1ZDAtOTI1Yi1lMjQxODFhYmMxODc",
        "key": "department_lead"
      }
    }
  }
}
mutation {
  createGroup(input: { key:"managers", name:"Managers", description: "Group for managers with access to all departments" }) {
    group {
      id
      key
    }
  }
}
{
  "data": {
    "createGroup": {
      "group": {
        "id": "R3JvdXA6NDM2ZDg4OTctMmNjYi00ZjQ3LWJiOGYtN2U2MzE4ZTVhNDM3",
        "key": "managers"
      }
    }
  }
}
POST - /_api/admin/users/import
HTTP/1.1
Host: <Your Authgear Project domain>
Authorization: Bearer <Admin API JWT Token>
Content-type: application/json
Body: {
    "identifier": "email",
    "records": [
        {
            "email": "user@example.com",
            "email_verified": true,
            "password": {
                "type": "bcrypt",
                "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
            }
        }
    ]
}
GET - /_api/admin/users/import/{ID}
HTTP/1.1
Host: <Your Authgear Project domain>
Authorization: Bearer <Admin API JWT Token>
npm install jsonwebtoken
function generateJWT() {
    const project_id = ""; //Your authgear app id
    const key_id = ""; //you authgear key ID
    const expiresAt = Math.floor(Date.now() / 1000) + (60 * 60); //the current value means token will expire in 1 hour.
    
    //Payload to include in JWT
    const claims = {
        aud: project_id,
        iat: Math.floor(Date.now() / 1000) - 30,
        exp: expiresAt
    }
    const privateKey = fs.readFileSync("key.pem"); //Read value from the downloaded key file
    const header = { "typ": "JWT", "kid": key_id, "alg": "RS256" }
    const jwt = node_jwt.sign(claims, privateKey, { header: header });

    return jwt;
}
npm install node-fetch
const express = require("express");
const node_jwt = require('jsonwebtoken');
const fs = require('fs');
const fetch = require('node-fetch');
const app = express();
const port = 3002;

//TODO Place declaration of generateJWT() function here

app.get('/', (request, response) => {

    const jwt = generateJWT();
    const data = {
        "identifier": "email",
        "records": [
            {
                "email": "user1@example.com",
                "email_verified": true,
                "password": {
                    "type": "bcrypt",
                    "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
                }
            },
            {
                "email": "user2@example.com",
                "email_verified": false,
                "name": "John Doe",
                "given_name": "John",
                "family_name": "Doe",
                "password": {
                    "type": "bcrypt",
                    "password_hash": "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"
                }
            }
        ]
    }

    const options = {
        method: 'POST',
        headers: { 'Content-type': 'application/json', 'Authorization': 'Bearer ' + jwt },
        body: JSON.stringify(data)
    };

    const appUrl = 'https://your-project.authgearapps.com'; // replace wuth your authgear project url

    fetch(`${appUrl}/_api/admin/users/import`, options)
        .then(result => result.json())
        .then(result => console.log(JSON.stringify(result)));

    response.send("Request sent using the follow JWT as Bearer: " + jwt + "See console for result");
});

app.listen(port, () => {
    console.log("server started! PORT: " + port);
});
{
  "id": "task_4WZ0V7EPT4GZ2ABVN03QXYZ122W835C1",
  "created_at": "2024-04-04T06:56:36.02508096Z",
  "status": "pending"
}
app.get("/status/:id", (request, response) => {
    const jwt = generateJWT()

    const options = {
        method: 'GET',
        headers: { 'Content-type': 'application/json', 'Authorization': 'Bearer ' + jwt }
    };

    const appUrl = 'https://your-project.authgearapps.com';

    fetch(`${appUrl}/_api/admin/users/import/${request.params.id}`, options)
        .then(result => result.json())
        .then(result => console.log(JSON.stringify(result)));

    response.send("Request sent using the follow JWT as Bearer: " + jwt + "See console for result");
});
{
  "id": "task_4WZ0V7EPT4GZ2ABVN03QXYZ122W835C1",
  "created_at": "2024-04-04T06:56:36.02508096Z",
  "status": "completed",
  "summary": {
    "total": 2,
    "inserted": 2,
    "updated": 0,
    "skipped": 0,
    "failed": 0
  },
  "details": [
    {
      "index": 0,
      "record": {
        "email": "user1@example.com",
        "email_verified": true,
        "password": {
          "password_hash": "REDACTED",
          "type": "bcrypt"
        }
      },
      "outcome": "inserted",
      "user_id": "0f0f65ee-4c7d-45a0-a740-bcbbfd3fcf06"
    },
    {
      "index": 1,
      "record": {
        "email": "user2@example.com",
        "email_verified": false,
        "family_name": "Doe",
        "given_name": "John",
        "name": "John Doe",
        "password": {
          "password_hash": "REDACTED",
          "type": "bcrypt"
        }
      },
      "outcome": "inserted",
      "user_id": "9c71fc29-6db6-4a18-aa73-774139fed16d",
      "warnings": [
        {
          "message": "email_verified = false has no effect in insert."
        }
      ]
    }
  ]
}

Content-Type

application/json

Authorization

Bearer <Admin API JWT Token>

Host

<Your Authgear Project domain>

{
  "format": "csv",
  "csv": {
    "fields": [
      {
        "pointer": "/sub",
        "field_name": "user_id"
      },
      {
        "pointer": "/email"
      }
    ]
  }
}

Authorization

Bearer <Admin API JWT Token>

Host

<Your Authgear Project domain>

npm install jsonwebtoken
const node_jwt = require('jsonwebtoken');
const fs = require("fs");

function generateJWT() {
    const project_id = ""; //Your authgear app id
    const key_id = ""; //you authgear key ID
    const expiresAt = Math.floor(Date.now() / 1000) + (60 * 60); //the current value means token will expire in 1 hour.
    
    //Payload to include in JWT
    const claims = {
        aud: project_id,
        iat: Math.floor(Date.now() / 1000) - 30,
        exp: expiresAt
    }
    const privateKey = fs.readFileSync("key.pem"); //Read value from the downloaded key file
    const header = { "typ": "JWT", "kid": key_id, "alg": "RS256" }
    const jwt = node_jwt.sign(claims, privateKey, { header: header });

    return jwt;
}
npm install node-fetch
const express = require("express");
const node_jwt = require("jsonwebtoken");
const fs = require("fs");
const fetch = require("node-fetch");
const app = express();
const port = 3002;

app.get("/export", (request, response) => {
  const jwt = generateJWT();
  const input = {
    format: "csv",
    csv: {
      fields: [
        {
          pointer: "/sub",
          field_name: "user_id",
        },
        {
          pointer: "/email",
        },
      ],
    },
  };

  const options = {
    method: "POST",
    headers: {
      "Content-type": "application/json",
      Authorization: "Bearer " + jwt,
    },
    body: JSON.stringify(input),
  };

  const appUrl = "https://your-project.authgearapps.com";

  fetch(`${appUrl}/_api/admin/users/export`, options)
    .then((result) => result.json())
    .then((result) => response.send(result))
    .catch((error) => response.send(error));
});

app.listen(port, () => {
  console.log("server started! PORT: " + port);
});
{
    "result": {
        "id": "userexport_VWFAACAMB5V0BY1J7KK5NS3GV1TQAACQ",
        "created_at": "2024-10-07T21:06:24.361634372Z",
        "status": "pending",
        "request": {
            "format": "csv",
            "csv": {
                "fields": [
                    {
                        "pointer": "/sub",
                        "field_name": "user_id"
                    },
                    {
                        "pointer": "/email"
                    },
                    {
                        "pointer": "/mfa/emails"
                    }
                ]
            }
        }
    }
}
app.get("/status/:id", (request, response) => {
  const jwt = generateJWT();

  const options = {
    method: "GET",
    headers: {
      "Content-type": "application/json",
      Authorization: "Bearer " + jwt,
    },
  };

  const appUrl = "https://your-project.authgearapps.com";

  fetch(`${appUrl}/_api/admin/users/export/${request.params.id}`, options)
    .then((result) => result.json())
    .then((result) => response.send(result))
    .catch((error) => response.send(error));

  
});
{
    "result": {
        "id": "userexport_VWFAACAMB5V0BY1J7KK5NS3GV1TQAACQ",
        "created_at": "2024-10-07T21:06:24.361634372Z",
        "completed_at": "2024-10-07T21:06:24.551711713Z",
        "status": "completed",
        "request": {
            "format": "csv",
            "csv": {
                "fields": [
                    {
                        "pointer": "/sub",
                        "field_name": "user_id"
                    },
                    {
                        "pointer": "/email"
                    },
                    {
                        "pointer": "/mfa/emails"
                    }
                ]
            }
        },
        "download_url": "https://storage.googleapis.com/authgear-userexport-staging/example-userexport_userexport_VWFAACAMB5V0BY1J7KK5NS3GV1TQAACQ-20241007210624Z.csv?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=authgear-server%40oursky-kube.iam.gserviceaccount.com%2F20241007%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20241007T210641Z&X-Goog-Expires=59&X-Goog-Signature=abcd12e45&X-Goog-SignedHeaders=host"
    }
}
roles and group flowchart
navigate to roles management page
create new role page
navigate to groups management page
Apple announced
Apple decided
User Settings
Admin API
Admin API
Webhooks
UserInfo endpoint
Admin API
necessary authorization to interact with the Admin API
access to the Admin API endpoint
Admin API JWT token
User Import API Reference
here
Node.js
Admin API Authentication
CSV
ndjson
Admin API JWT token
Admin API Authentication
how to create roles
User Export API Reference
Your Authgear Endpoint
example
example
example
example
example
UserInfo
retrieve the "UserInfo" object
"Delete your account" button in the User Settings page
Admin API GraphiQL Explorer
API input format