$npx -y skills add BoltzmannEntropy/OSXSkills --skill osx-flutter-auth0-loginUse when adding login/authentication to a Flutter macOS app (desktop) using Auth0. Includes Auth0 tenant setup, macOS callback configuration, Flutter login UI and AuthService, secure token storage, logout, and a backend JWT verification example.
| 1 | # Flutter macOS Login with Auth0 |
| 2 | |
| 3 | ## Scope and Goals |
| 4 | |
| 5 | Implement production-ready login for a Flutter app running on macOS using Auth0 Universal Login with Authorization Code Flow + PKCE. |
| 6 | |
| 7 | Deliverables: |
| 8 | - Auth0 configuration steps (Native app) |
| 9 | - Flutter macOS login UI screen |
| 10 | - Auth service for login, logout, token caching and refresh |
| 11 | - Secure token storage using Keychain via flutter_secure_storage |
| 12 | - Backend example that validates access tokens using JWKS |
| 13 | - Clear separation of dev vs prod settings (domain, clientId, audience, redirect URIs) |
| 14 | |
| 15 | Use the Auth0 Flutter SDK patterns and recommended flows. |
| 16 | |
| 17 | ## When to Use |
| 18 | |
| 19 | - User asks for "login", "sign in", "Auth0", "OAuth", "SSO", "Google login", "Apple login" |
| 20 | - App is Flutter and targets macOS desktop |
| 21 | - There is an API backend that needs authenticated requests |
| 22 | |
| 23 | ## Non Goals |
| 24 | |
| 25 | - Do not implement username/password collection inside the app UI. |
| 26 | - Do not embed client secrets in the client app. |
| 27 | - Do not implement ROPC. |
| 28 | |
| 29 | Use system browser and PKCE. |
| 30 | |
| 31 | ## Architecture Summary |
| 32 | |
| 33 | - Flutter app uses Auth0 Universal Login in system browser (ASWebAuthenticationSession on Apple platforms). |
| 34 | - App receives callback via custom URL scheme (and optionally Universal Links on newer macOS versions). |
| 35 | - App stores tokens in Keychain. |
| 36 | - App calls backend with Authorization: Bearer <access_token>. |
| 37 | - Backend validates JWT using JWKS and checks issuer, audience, and exp. |
| 38 | |
| 39 | Auth0 docs emphasize Authorization Code with PKCE for native apps. |
| 40 | |
| 41 | ## Auth0 Dashboard Setup (Native Application) |
| 42 | |
| 43 | 1. Create an Auth0 Application of type "Native". |
| 44 | 2. Note: |
| 45 | - Domain (example: your-tenant.us.auth0.com) |
| 46 | - Client ID |
| 47 | 3. Configure Callback URLs and Logout URLs: |
| 48 | - Custom scheme callback (recommended baseline): |
| 49 | - com.example.myapp://callback |
| 50 | - com.example.myapp://logout |
| 51 | - If you opt into Universal Links on macOS 14.4+ you can add those too, but keep custom scheme for fallback. |
| 52 | 4. Configure Allowed Web Origins if needed for any embedded web contexts (generally not needed for system browser flows on macOS). |
| 53 | 5. If the backend is an API: |
| 54 | - Create an Auth0 API (audience identifier like https://api.example.com) |
| 55 | - Define scopes (read:stuff, write:stuff) |
| 56 | - The Flutter app will request audience + scopes to obtain an access token intended for your API. |
| 57 | |
| 58 | ## Flutter Dependencies |
| 59 | |
| 60 | Prefer the official Auth0 Flutter SDK. |
| 61 | |
| 62 | Add: |
| 63 | - auth0_flutter |
| 64 | - flutter_secure_storage |
| 65 | |
| 66 | Example: |
| 67 | |
| 68 | ```yaml |
| 69 | dependencies: |
| 70 | auth0_flutter: ^1.7.0 |
| 71 | flutter_secure_storage: ^9.0.0 |
| 72 | ``` |
| 73 | |
| 74 | Auth0 provides a Flutter quickstart and the pub.dev package documents macOS support and callback behavior. |
| 75 | |
| 76 | ## macOS App Configuration (Callback Handling) |
| 77 | |
| 78 | Set a custom URL scheme for the macOS runner so the app can receive: |
| 79 | |
| 80 | - com.example.myapp://callback |
| 81 | |
| 82 | In macOS Runner Info.plist, include CFBundleURLTypes. The Auth0 examples describe registering the bundle identifier or scheme so callbacks reach the app. |
| 83 | |
| 84 | Example Info.plist snippet: |
| 85 | |
| 86 | ```xml |
| 87 | <key>CFBundleURLTypes</key> |
| 88 | <array> |
| 89 | <dict> |
| 90 | <key>CFBundleURLName</key> |
| 91 | <string>com.example.myapp</string> |
| 92 | <key>CFBundleURLSchemes</key> |
| 93 | <array> |
| 94 | <string>com.example.myapp</string> |
| 95 | </array> |
| 96 | </dict> |
| 97 | </array> |
| 98 | ``` |
| 99 | |
| 100 | Redirect URI becomes: |
| 101 | |
| 102 | - com.example.myapp://callback |
| 103 | |
| 104 | Logout return URI becomes: |
| 105 | |
| 106 | - com.example.myapp://logout |
| 107 | |
| 108 | ## macOS Entitlements (Keychain Access) |
| 109 | |
| 110 | For flutter_secure_storage to work in sandboxed macOS apps, configure Keychain entitlements. |
| 111 | |
| 112 | In `macos/Runner/Release.entitlements` and `macos/Runner/DebugProfile.entitlements`: |
| 113 | |
| 114 | ```xml |
| 115 | <key>keychain-access-groups</key> |
| 116 | <array> |
| 117 | <string>$(AppIdentifierPrefix)com.example.myapp</string> |
| 118 | </array> |
| 119 | ``` |
| 120 | |
| 121 | If the app is sandboxed (required for App Store), also ensure: |
| 122 | |
| 123 | ```xml |
| 124 | <key>com.apple.security.app-sandbox</key> |
| 125 | <true/> |
| 126 | ``` |
| 127 | |
| 128 | ## App Configuration Model |
| 129 | |
| 130 | Create a single source of truth for auth config: |
| 131 | |
| 132 | - Auth0 domain |
| 133 | - clientId |
| 134 | - audience |
| 135 | - redirectUri |
| 136 | - logoutUri |
| 137 | |
| 138 | Support env switching: |
| 139 | |
| 140 | - dev, staging, prod |
| 141 | |
| 142 | Example: |
| 143 | |
| 144 | ```dart |
| 145 | class AuthConfig { |
| 146 | final String domain; |
| 147 | final String clientId; |
| 148 | final String audience; |
| 149 | final String redirectUri; |
| 150 | final String logoutUri; |
| 151 | |
| 152 | const AuthConfig({ |
| 153 | required this.domain, |
| 154 | required this.clientId, |
| 155 | required this.audience, |
| 156 | required this.redirectUri, |
| 157 | required this.logoutUri, |
| 158 | }); |
| 159 | } |
| 160 | ``` |
| 161 | |
| 162 | ## Token Storage (Keychain) |
| 163 | |
| 164 | Store: |
| 165 | |
| 166 | - accessToken |
| 167 | - idToken |
| 168 | - refreshToken (only if enabled) |
| 169 | - expiresAt |
| 170 | |
| 171 | Use flutter_secure_storage which maps to Keychain on macOS. |
| 172 | |
| 173 | Keys: |
| 174 | |
| 175 | - auth.accessToken |
| 176 | - auth.idToken |
| 177 | - auth.refreshToken |
| 178 | - auth.expiresAt |
| 179 | |
| 180 | ## AuthService Implementation (Dart) |
| 181 | |
| 182 | AuthService responsibilities: |
| 183 | |
| 184 | - login() using Auth0WebAuth (system browser) with PKCE |
| 185 | - logout() |
| 186 | - getVal |