auth0-ionic-angular

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Auth0 Ionic Angular (Capacitor) Integration

Auth0 Ionic Angular(Capacitor)集成方案

Add authentication to an Ionic Angular application using the
@auth0/auth0-angular
SDK with Capacitor plugins for native iOS and Android. This skill covers login, logout, user profile display, and secure token management using the system browser (SFSafariViewController on iOS, Chrome Custom Tabs on Android) via Capacitor's Browser plugin.
借助
@auth0/auth0-angular
SDK和Capacitor插件,为Ionic Angular应用添加认证功能,适配原生iOS和Android平台。本方案涵盖登录、登出、用户资料展示,以及通过Capacitor的Browser插件调用系统浏览器(iOS端为SFSafariViewController,Android端为Chrome Custom Tabs)实现安全的令牌管理。

Prerequisites

前置条件

  • Node.js 20+ and npm 10+
  • Ionic CLI (
    npm install -g @ionic/cli
    )
  • Capacitor 5+ configured in the project
  • Auth0 CLI (for automatic setup):
    brew install auth0/auth0-cli/auth0
  • An Auth0 account (free tier works)
  • Node.js 20+ 及 npm 10+
  • Ionic CLI(执行
    npm install -g @ionic/cli
    安装)
  • 项目中已配置Capacitor 5+
  • Auth0 CLI(用于自动配置:
    brew install auth0/auth0-cli/auth0
  • 一个Auth0账号(免费版即可)

When NOT to Use

不适用于以下场景

Use CaseRecommended Skill
Ionic React app with Capacitor
auth0-ionic-react
Ionic Vue app with Capacitor
auth0-ionic-vue
Angular SPA (browser-only, no Capacitor)
auth0-angular
or
auth0-react
React Native (no Ionic)
auth0-react-native
Expo (React Native)
auth0-expo
Native iOS (Swift)
auth0-swift
Native Android (Kotlin)
auth0-android
使用场景推荐方案
搭载Capacitor的Ionic React应用
auth0-ionic-react
搭载Capacitor的Ionic Vue应用
auth0-ionic-vue
Angular单页应用(仅浏览器端,无Capacitor)
auth0-angular
auth0-react
React Native(无Ionic)
auth0-react-native
Expo(React Native)
auth0-expo
原生iOS(Swift)
auth0-swift
原生Android(Kotlin)
auth0-android

Quick Start Workflow

快速开始流程

Agent instruction: Follow these steps in order. Always use
AskUserQuestion
to let the developer choose between Automatic Setup and Manual Setup before proceeding — even if credentials are already provided in the prompt.
SECURITY — Never display credentials: After obtaining Auth0 credentials (domain, client ID) via the CLI or from a file, NEVER print, echo, or display them in your text output. Write them directly to the config file (
src/environments/environment.ts
) silently. Do NOT produce output like "Domain: xxx" or "Client ID: yyy". Instead, confirm that the config file has been written and tell the user where to find it.
UI reuse: Before creating new login/logout components, search the existing project for login/logout handlers or buttons. If found, hook Auth0 into the existing UI rather than creating duplicate components.
Agent指令: 请按顺序执行以下步骤。无论提示中是否已提供凭证,都必须先使用
AskUserQuestion
让开发者选择自动配置还是手动配置,再继续操作。
安全注意事项——切勿显示凭证: 通过CLI或文件获取Auth0凭证(域名、客户端ID)后,绝对不要在文本输出中打印、回显或展示这些信息。请直接将其静默写入配置文件
src/environments/environment.ts
。不要输出类似“域名:xxx”或“客户端ID:yyy”的内容,只需确认配置文件已写入,并告知用户文件位置即可。
UI复用: 在创建新的登录/登出组件前,请先搜索现有项目中是否存在登录/登出处理器或按钮。如果存在,请将Auth0集成到现有UI中,避免创建重复组件。

Step 1: Install Dependencies

步骤1:安装依赖

bash
npm install @auth0/auth0-angular @capacitor/browser @capacitor/app
bash
npm install @auth0/auth0-angular @capacitor/browser @capacitor/app

Step 2: Configure Auth0

步骤2:配置Auth0

Agent instruction: Always present the setup choice using
AskUserQuestion
— even if the user has already provided credentials:
AskUserQuestion:
  question: "How would you like to configure Auth0 for your Ionic Angular app?"
  options:
    - label: "Automatic Setup (Recommended)"
      description: "Uses the Auth0 CLI to create a Native application, configure callback URLs, and store credentials in your project automatically."
    - label: "Manual Setup"
      description: "You provide an .env file with your Auth0 Domain and Client ID, and the agent reads it and writes the project configuration for you."
Follow the chosen path in the Setup Guide which has the full step-by-step instructions for both options.
Auth0 Dashboard settings (Native application type):
SettingValue
Application TypeNative
Allowed Callback URLs
PACKAGE_ID://YOUR_DOMAIN/capacitor/PACKAGE_ID/callback
Allowed Logout URLs
PACKAGE_ID://YOUR_DOMAIN/capacitor/PACKAGE_ID/callback
Allowed Origins
capacitor://localhost, http://localhost
Replace
PACKAGE_ID
with your
appId
from
capacitor.config.ts
(e.g.,
com.example.myapp
) and
YOUR_DOMAIN
with your Auth0 domain.
Note: For Automatic Setup, these URLs are configured automatically by the Auth0 CLI. For Manual Setup, the user must configure them in the Auth0 Dashboard.
Note: For local web development (
ionic serve
), also add
http://localhost:8100
to Allowed Callback URLs, Allowed Logout URLs, and Allowed Web Origins.
Agent指令: 无论用户是否已提供凭证,都必须通过
AskUserQuestion
提供配置选项:
AskUserQuestion:
  question: "您希望如何为Ionic Angular应用配置Auth0?"
  options:
    - label: "自动配置(推荐)"
      description: "使用Auth0 CLI创建Native应用、配置回调URL,并自动将凭证存储到项目中。"
    - label: "手动配置"
      description: "您提供包含Auth0域名和客户端ID的.env文件,Agent会读取并写入项目配置。"
根据选择的方式,遵循配置指南中的完整分步说明操作。
Auth0控制台设置(Native应用类型):
设置项
应用类型Native
允许的回调URL
PACKAGE_ID://YOUR_DOMAIN/capacitor/PACKAGE_ID/callback
允许的登出URL
PACKAGE_ID://YOUR_DOMAIN/capacitor/PACKAGE_ID/callback
允许的源
capacitor://localhost, http://localhost
PACKAGE_ID
替换为
capacitor.config.ts
中的
appId
(例如
com.example.myapp
),
YOUR_DOMAIN
替换为您的Auth0域名。
注意: 自动配置时,这些URL会由Auth0 CLI自动配置。手动配置时,用户必须在Auth0控制台中完成配置。
注意: 对于本地Web开发(
ionic serve
),还需将
http://localhost:8100
添加到允许的回调URL、允许的登出URL和允许的Web源中。

Step 3: Configure the SDK

步骤3:配置SDK

In
src/app/app.module.ts
(NgModule) or
src/app/app.config.ts
(standalone):
The
provideAuth0()
function (or
AuthModule.forRoot()
) is the Angular equivalent of
Auth0Provider
— it acts as the provider/wrapper that wraps the app and makes
AuthService
available everywhere. For local web development with
ionic serve
, the callback URL is
http://localhost:8100
.
Standalone (Angular 17+):
typescript
import { ApplicationConfig } from '@angular/core';
import { provideAuth0 } from '@auth0/auth0-angular';

// Replace with your capacitor.config.ts appId and Auth0 domain
const appId = 'com.example.myapp';
const domain = 'YOUR_AUTH0_DOMAIN';
const callbackUri = `${appId}://${domain}/capacitor/${appId}/callback`;

export const appConfig: ApplicationConfig = {
  providers: [
    provideAuth0({
      domain,
      clientId: 'YOUR_AUTH0_CLIENT_ID',
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri: callbackUri,
      },
    }),
  ],
};
NgModule (Angular 16 and earlier):
typescript
import { AuthModule } from '@auth0/auth0-angular';

const appId = 'com.example.myapp';
const domain = 'YOUR_AUTH0_DOMAIN';
const callbackUri = `${appId}://${domain}/capacitor/${appId}/callback`;

@NgModule({
  imports: [
    AuthModule.forRoot({
      domain,
      clientId: 'YOUR_AUTH0_CLIENT_ID',
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri: callbackUri,
      },
    }),
  ],
})
export class AppModule {}
src/app/app.module.ts
(NgModule模式)或
src/app/app.config.ts
(独立组件模式)中配置:
provideAuth0()
函数(或
AuthModule.forRoot()
)是Angular版本的
Auth0Provider
——它作为提供者/包装器包裹应用,使
AuthService
可在全局使用。对于使用
ionic serve
的本地Web开发,回调URL为
http://localhost:8100
独立组件模式(Angular 17+):
typescript
import { ApplicationConfig } from '@angular/core';
import { provideAuth0 } from '@auth0/auth0-angular';

// 替换为您的capacitor.config.ts中的appId和Auth0域名
const appId = 'com.example.myapp';
const domain = 'YOUR_AUTH0_DOMAIN';
const callbackUri = `${appId}://${domain}/capacitor/${appId}/callback`;

export const appConfig: ApplicationConfig = {
  providers: [
    provideAuth0({
      domain,
      clientId: 'YOUR_AUTH0_CLIENT_ID',
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri: callbackUri,
      },
    }),
  ],
};
NgModule模式(Angular 16及更早版本):
typescript
import { AuthModule } from '@auth0/auth0-angular';

const appId = 'com.example.myapp';
const domain = 'YOUR_AUTH0_DOMAIN';
const callbackUri = `${appId}://${domain}/capacitor/${appId}/callback`;

@NgModule({
  imports: [
    AuthModule.forRoot({
      domain,
      clientId: 'YOUR_AUTH0_CLIENT_ID',
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri: callbackUri,
      },
    }),
  ],
})
export class AppModule {}

Step 4: Handle Deep Link Callbacks (AppComponent)

步骤4:处理深度链接回调(AppComponent)

Register the
appUrlOpen
listener at the app root so it persists across navigation:
typescript
import { Component, NgZone, OnInit } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { Browser } from '@capacitor/browser';
import { App as CapApp } from '@capacitor/app';
import { mergeMap } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  template: `<ion-app><ion-router-outlet></ion-router-outlet></ion-app>`,
})
export class AppComponent implements OnInit {
  constructor(
    private auth: AuthService,
    private ngZone: NgZone
  ) {}

  ngOnInit() {
    CapApp.addListener('appUrlOpen', ({ url }) => {
      this.ngZone.run(() => {
        if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
          this.auth
            .handleRedirectCallback(url)
            .pipe(mergeMap(() => Browser.close()))
            .subscribe();
        }
      });
    });
  }
}
在应用根节点注册
appUrlOpen
监听器,使其在导航过程中持续生效:
typescript
import { Component, NgZone, OnInit } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { Browser } from '@capacitor/browser';
import { App as CapApp } from '@capacitor/app';
import { mergeMap } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  template: `<ion-app><ion-router-outlet></ion-router-outlet></ion-app>`,
})
export class AppComponent implements OnInit {
  constructor(
    private auth: AuthService,
    private ngZone: NgZone
  ) {}

  ngOnInit() {
    CapApp.addListener('appUrlOpen', ({ url }) => {
      this.ngZone.run(() => {
        if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
          this.auth
            .handleRedirectCallback(url)
            .pipe(mergeMap(() => Browser.close()))
            .subscribe();
        }
      });
    });
  }
}

Step 5: Implement Login

步骤5:实现登录功能

typescript
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { Browser } from '@capacitor/browser';

@Component({
  selector: 'app-login',
  template: `<ion-button (click)="login()">Log In</ion-button>`,
})
export class LoginPage {
  constructor(public auth: AuthService) {}

  login() {
    this.auth
      .loginWithRedirect({
        async openUrl(url: string) {
          await Browser.open({ url, windowName: '_self' });
        },
      })
      .subscribe();
  }
}
typescript
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { Browser } from '@capacitor/browser';

@Component({
  selector: 'app-login',
  template: `<ion-button (click)="login()">登录</ion-button>`,
})
export class LoginPage {
  constructor(public auth: AuthService) {}

  login() {
    this.auth
      .loginWithRedirect({
        async openUrl(url: string) {
          await Browser.open({ url, windowName: '_self' });
        },
      })
      .subscribe();
  }
}

Step 6: Implement Logout

步骤6:实现登出功能

typescript
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { Browser } from '@capacitor/browser';

@Component({
  selector: 'app-logout-button',
  template: `<ion-button (click)="logout()">Log Out</ion-button>`,
})
export class LogoutButtonComponent {
  constructor(public auth: AuthService) {}

  logout() {
    this.auth
      .logout({
        logoutParams: {
          returnTo: `YOUR_PACKAGE_ID://YOUR_AUTH0_DOMAIN/capacitor/YOUR_PACKAGE_ID/callback`,
        },
        async openUrl(url: string) {
          await Browser.open({ url, windowName: '_self' });
        },
      })
      .subscribe();
  }
}
typescript
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { Browser } from '@capacitor/browser';

@Component({
  selector: 'app-logout-button',
  template: `<ion-button (click)="logout()">登出</ion-button>`,
})
export class LogoutButtonComponent {
  constructor(public auth: AuthService) {}

  logout() {
    this.auth
      .logout({
        logoutParams: {
          returnTo: `YOUR_PACKAGE_ID://YOUR_AUTH0_DOMAIN/capacitor/YOUR_PACKAGE_ID/callback`,
        },
        async openUrl(url: string) {
          await Browser.open({ url, windowName: '_self' });
        },
      })
      .subscribe();
  }
}

Step 7: Display User Profile

步骤7:展示用户资料

typescript
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { AsyncPipe } from '@angular/common';

@Component({
  selector: 'app-profile',
  template: `
    <div *ngIf="auth.user$ | async as user">
      <img [src]="user.picture" [alt]="user.name" />
      <h2>{{ user.name }}</h2>
      <p>{{ user.email }}</p>
    </div>
  `,
})
export class ProfileComponent {
  constructor(public auth: AuthService) {}
}
typescript
import { Component } from '@angular/core';
import { AuthService } from '@auth0/auth0-angular';
import { AsyncPipe } from '@angular/common';

@Component({
  selector: 'app-profile',
  template: `
    <div *ngIf="auth.user$ | async as user">
      <img [src]="user.picture" [alt]="user.name" />
      <h2>{{ user.name }}</h2>
      <p>{{ user.email }}</p>
    </div>
  `,
})
export class ProfileComponent {
  constructor(public auth: AuthService) {}
}

Step 8: Build and Test

步骤8:构建并测试

Agent instruction: After writing all code, verify the build succeeds:
bash
npm run build
npx cap sync
If the build fails, investigate errors and fix (up to 5-6 iterations). If still failing, use
AskUserQuestion
to ask the user for help.
Agent指令: 编写完所有代码后,验证构建是否成功:
bash
npm run build
npx cap sync
如果构建失败,请排查错误并修复(最多尝试5-6次)。若仍失败,请使用
AskUserQuestion
向用户寻求帮助。

Detailed Documentation

详细文档

  • Setup Guide — Auth0 configuration, Auth0 CLI setup, Capacitor platform setup, deep linking
  • Integration Patterns — Login/logout flows, token management, user profile, error handling, Capacitor lifecycle
  • API Reference & Testing — AuthService API, configuration options, claims reference, testing checklist
  • 配置指南 — Auth0配置、Auth0 CLI设置、Capacitor平台设置、深度链接
  • 集成模式 — 登录/登出流程、令牌管理、用户资料、错误处理、Capacitor生命周期
  • API参考与测试 — AuthService API、配置选项、声明参考、测试清单

Common Mistakes

常见错误

MistakeFix
Auth0 app type set to SPA instead of NativeChange to Native in Auth0 Dashboard → Application Settings
Missing callback URL in Auth0 DashboardAdd
PACKAGE_ID://{domain}/capacitor/PACKAGE_ID/callback
to Allowed Callback URLs AND Allowed Logout URLs
Not wrapping
handleRedirectCallback
in
ngZone.run()
Angular won't detect auth state changes — always wrap in
ngZone.run()
Using
window.location.href
for login redirect
Must use
Browser.open()
from
@capacitor/browser
for system browser
useRefreshTokens
not set to
true
Required for mobile — localStorage is unreliable on native platforms
useRefreshTokensFallback
not set to
false
Must be
false
to avoid falling back to iframe-based token refresh (unsupported on mobile)
Missing
@capacitor/app
listener for deep links
The
appUrlOpen
listener is required to handle the callback from the system browser
Using
loginWithPopup
on mobile
Popups don't work on native — use
loginWithRedirect
with
Browser.open
Callback URL mismatch (scheme vs package ID)The URL scheme must match the
appId
in
capacitor.config.ts
exactly
错误修复方案
Auth0应用类型设置为SPA而非Native在Auth0控制台→应用设置中修改为Native
Auth0控制台中缺少回调URL
PACKAGE_ID://{domain}/capacitor/PACKAGE_ID/callback
添加到允许的回调URL和允许的登出URL中
未将
handleRedirectCallback
包裹在
ngZone.run()
Angular无法检测认证状态变化——必须始终包裹在
ngZone.run()
使用
window.location.href
进行登录重定向
必须使用
@capacitor/browser
中的
Browser.open()
调用系统浏览器
useRefreshTokens
未设置为
true
移动端必须开启——localStorage在原生平台不可靠
useRefreshTokensFallback
未设置为
false
必须设为
false
,避免回退到基于iframe的令牌刷新(移动端不支持)
缺少
@capacitor/app
的深度链接监听器
appUrlOpen
监听器是处理系统浏览器回调的必要条件
在移动端使用
loginWithPopup
弹窗在原生平台无法工作——使用
loginWithRedirect
搭配
Browser.open
回调URL不匹配(协议与包ID不一致)URL协议必须与
capacitor.config.ts
中的
appId
完全一致

WebAuth Method

WebAuth认证方式

Ionic with Capacitor uses the Web Auth method for authentication:
  1. User taps Log In → app calls
    loginWithRedirect
    with a custom
    openUrl
    that uses
    Browser.open()
  2. Capacitor's Browser plugin opens the Auth0 Universal Login page in the system browser (SFSafariViewController / Chrome Custom Tabs)
  3. User authenticates → Auth0 redirects to the custom URL scheme callback
  4. OS routes the deep link to your app →
    appUrlOpen
    event fires
  5. handleRedirectCallback(url)
    processes the auth code exchange inside
    ngZone.run()
  6. Browser.close()
    dismisses the system browser
  7. auth.isAuthenticated$
    emits
    true
    , and
    auth.user$
    emits the user profile
搭载Capacitor的Ionic应用使用Web Auth方式进行认证:
  1. 用户点击登录→应用调用
    loginWithRedirect
    ,并传入自定义
    openUrl
    ,该方法使用
    Browser.open()
  2. Capacitor的Browser插件在系统浏览器(SFSafariViewController / Chrome Custom Tabs)中打开Auth0通用登录页面
  3. 用户完成认证→Auth0重定向到自定义URL协议的回调地址
  4. 操作系统将深度链接路由到您的应用→触发
    appUrlOpen
    事件
  5. handleRedirectCallback(url)
    ngZone.run()
    中处理授权码交换
  6. Browser.close()
    关闭系统浏览器
  7. auth.isAuthenticated$
    发出
    true
    auth.user$
    发出用户资料

Related Skills

相关方案

  • auth0-ionic-react — Ionic React with Capacitor
  • auth0-ionic-vue — Ionic Vue with Capacitor
  • auth0-angular — Angular SPA (browser-only)
  • auth0-swift — Native iOS (Swift)
  • auth0-android — Native Android (Kotlin)
  • auth0-ionic-react — 搭载Capacitor的Ionic React应用
  • auth0-ionic-vue — 搭载Capacitor的Ionic Vue应用
  • auth0-angular — Angular单页应用(仅浏览器端)
  • auth0-swift — 原生iOS(Swift)应用
  • auth0-android — 原生Android(Kotlin)应用

Quick Reference

快速参考

APIDescription
AuthService.loginWithRedirect(options)
Start login flow with custom
openUrl
for Capacitor
AuthService.logout(options)
Log out with custom
openUrl
and
returnTo
AuthService.handleRedirectCallback(url)
Process the callback URL from the deep link
AuthService.isAuthenticated$
Observable boolean — whether user is logged in
AuthService.user$
Observable — current user profile (name, email, picture)
AuthService.isLoading$
Observable boolean — SDK initialization state
AuthService.error$
Observable — authentication errors
AuthService.getAccessTokenSilently()
Get access token (uses refresh tokens on mobile)
Browser.open({ url })
Open URL in system browser (Capacitor)
CapApp.addListener('appUrlOpen', cb)
Listen for deep link callbacks (Capacitor)
API描述
AuthService.loginWithRedirect(options)
启动登录流程,为Capacitor传入自定义
openUrl
AuthService.logout(options)
执行登出操作,传入自定义
openUrl
returnTo
AuthService.handleRedirectCallback(url)
处理深度链接中的回调URL
AuthService.isAuthenticated$
可观察布尔值——表示用户是否已登录
AuthService.user$
可观察对象——当前用户资料(姓名、邮箱、头像)
AuthService.isLoading$
可观察布尔值——SDK初始化状态
AuthService.error$
可观察对象——认证错误信息
AuthService.getAccessTokenSilently()
获取访问令牌(移动端使用刷新令牌)
Browser.open({ url })
在系统浏览器中打开URL(Capacitor)
CapApp.addListener('appUrlOpen', cb)
监听深度链接回调(Capacitor)

References

参考链接