{"id":48708389,"url":"https://github.com/SamsonGross/ngx-cognito-auth","last_synced_at":"2026-04-13T11:01:12.984Z","repository":{"id":346790012,"uuid":"1190611035","full_name":"SamsonGross/ngx-cognito-auth","owner":"SamsonGross","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-25T12:22:29.000Z","size":58,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-26T15:27:58.452Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SamsonGross.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-24T13:01:03.000Z","updated_at":"2026-03-25T12:22:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SamsonGross/ngx-cognito-auth","commit_stats":null,"previous_names":["samsongross/ngx-cognito-auth"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/SamsonGross/ngx-cognito-auth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamsonGross%2Fngx-cognito-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamsonGross%2Fngx-cognito-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamsonGross%2Fngx-cognito-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamsonGross%2Fngx-cognito-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SamsonGross","download_url":"https://codeload.github.com/SamsonGross/ngx-cognito-auth/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamsonGross%2Fngx-cognito-auth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31749763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T09:16:15.125Z","status":"ssl_error","status_checked_at":"2026-04-13T09:16:05.023Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-11T13:00:21.203Z","updated_at":"2026-04-13T11:01:12.970Z","avatar_url":"https://github.com/SamsonGross.png","language":"TypeScript","funding_links":[],"categories":["Security and Authentication"],"sub_categories":["Authentication"],"readme":"# ngx-cognito-auth\n\nAngular 21+ library for AWS Cognito authentication using the **OAuth 2.0 Authorization Code flow with PKCE**. No client secret required — safe for browser-based SPAs.\n\n## Features\n\n- PKCE-secured login flow (no client secret)\n- Silent token refresh via refresh token\n- Automatic Bearer token injection on every HTTP request\n- Automatic pre-request token refresh when access token is expired\n- Route guard that redirects unauthenticated users to Cognito\n- Callback resolver that handles the OAuth redirect\n- Angular Signals-based reactive state (`accessToken`, `user`, `isAuthenticated`)\n- Token storage: access + ID token in `sessionStorage`, refresh token in `localStorage`\n\n---\n\n## Requirements\n\n| Dependency        | Version     |\n| ----------------- | ----------- |\n| `@angular/core`   | `\u003e= 21.0.0` |\n| `@angular/common` | `\u003e= 21.0.0` |\n| `@angular/router` | `\u003e= 21.0.0` |\n| `rxjs`            | `\u003e= 7.0.0`  |\n\n---\n\n## Installation\n\n```bash\nnpm install ngx-cognito-auth\n```\n\n---\n\n## AWS Cognito Setup\n\n### 1. Create a User Pool\n\n1. Open the [AWS Console](https://console.aws.amazon.com/cognito) and navigate to **Cognito → User Pools**\n2. Click **Create user pool**\n3. Configure sign-in options (e.g. email, username)\n4. Under **Password policy**, choose your requirements\n5. Under **Multi-factor authentication**, configure as needed\n6. Under **User account recovery**, enable email recovery if desired\n7. Complete the wizard and note down the **User Pool ID** (e.g. `eu-central-1_AbCdEfGhI`)\n\n### 2. Create an App Client\n\n1. Inside your User Pool, go to **App integration → App clients → Create app client**\n2. Set **App client name** (e.g. `my-angular-app`)\n3. **Client type**: select **Public client** — leave **Generate a client secret** unchecked (SPAs cannot safely store a secret)\n4. Under **Authentication flows**, enable `ALLOW_USER_SRP_AUTH` and `ALLOW_REFRESH_TOKEN_AUTH`\n5. Note down the **Client ID**\n\n### 3. Configure the Hosted UI\n\n1. In **App integration**, go to your app client → **Hosted UI**\n2. Under **Allowed callback URLs**, add your redirect URI, e.g.:\n   - `http://localhost:4200/callback` (development)\n   - `https://your-production-domain.com/callback` (production)\n3. Under **Allowed sign-out URLs**, add:\n   - `http://localhost:4200/` (development)\n   - `https://your-production-domain.com/` (production)\n4. Under **OAuth 2.0 grant types**, enable **Authorization code grant**\n5. Under **OpenID Connect scopes**, select: `openid`, `email`, `profile`\n6. Under **Domain**, either use a Cognito-managed domain or your own custom domain. Note the full domain, e.g.:\n   `eu-central-1zfcbvs02q.auth.eu-central-1.amazoncognito.com`\n\n\u003e **Important:** The redirect URI registered in Cognito must exactly match the `redirectUri` in your Angular config, including protocol and path.\n\n---\n\n## Configuration\n\n### Environment Variables (`.env`)\n\nCreate a `.env` file in the project root. This file is **not committed to version control** — add it to `.gitignore`.\n\n```dotenv\nCOGNITO_USER_POOL_ID=eu-central-1_AbCdEfGhI\nCOGNITO_CLIENT_ID=47skdqidmdot9sj7i1d9kuo0c0\nCOGNITO_DOMAIN=eu-central-1abcdefghi.auth.eu-central-1.amazoncognito.com\nCOGNITO_REDIRECT_URI=http://localhost:4200/callback\n```\n\nThe `scripts/set-env.js` script reads this file and writes `projects/demo/src/app/environments/environment.ts` automatically before every `npm start` and `npm run build:demo` (via `prestart` / `prebuild:demo` hooks).\n\nRun it manually at any time:\n\n```bash\nnode scripts/set-env.js\n```\n\n### `CognitoAuthConfig` Reference\n\n| Field              | Type       | Required | Default        | Description                                                        |\n| ------------------ | ---------- | -------- | -------------- | ------------------------------------------------------------------ |\n| `userPoolId`       | `string`   | ✅       | —              | User Pool ID, e.g. `eu-central-1_AbCdEfGhI`                        |\n| `clientId`         | `string`   | ✅       | —              | App client ID (no secret)                                          |\n| `domain`           | `string`   | ✅       | —              | Hosted UI domain, e.g. `myapp.auth.eu-central-1.amazoncognito.com` |\n| `redirectUri`      | `string`   | ✅       | —              | Full callback URI registered in Cognito                            |\n| `scopes`           | `string[]` | ✅       | —              | OAuth scopes, e.g. `['openid', 'email', 'profile']`                |\n| `postLoginRoute`   | `string`   | —        | `'/dashboard'` | App route to navigate to after login                               |\n| `postLogoutRoute`  | `string`   | —        | `'/'`          | App route for Cognito's `logout_uri` after logout                  |\n| `storageKeyPrefix` | `string`   | —        | `'cog_auth'`   | Prefix for all `sessionStorage` / `localStorage` keys              |\n\n---\n\n## Setup\n\n### Standalone App (`app.config.ts`)\n\n```typescript\nimport { ApplicationConfig } from \"@angular/core\";\nimport { provideRouter } from \"@angular/router\";\nimport { provideHttpClient } from \"@angular/common/http\";\nimport { provideCognitoAuth, withCognitoInterceptor } from \"ngx-cognito-auth\";\nimport { routes } from \"./app.routes\";\nimport { environment } from \"./environments/environment\";\n\nexport const appConfig: ApplicationConfig = {\n  providers: [\n    provideRouter(routes),\n    provideHttpClient(withCognitoInterceptor()), // registers the Bearer interceptor\n    provideCognitoAuth(environment.cognito), // registers service, guard, resolver + initializer\n  ],\n};\n```\n\n### NgModule App (`app.module.ts`)\n\n```typescript\nimport { NgModule } from \"@angular/core\";\nimport { HttpClientModule } from \"@angular/common/http\";\nimport { HTTP_INTERCEPTORS } from \"@angular/common/http\";\nimport { CognitoAuthModule, cognitoBearerInterceptor } from \"ngx-cognito-auth\";\nimport { environment } from \"../environments/environment\";\n\n@NgModule({\n  imports: [HttpClientModule, CognitoAuthModule.forRoot(environment.cognito)],\n  providers: [\n    {\n      provide: HTTP_INTERCEPTORS,\n      useValue: cognitoBearerInterceptor,\n      multi: true,\n    },\n  ],\n})\nexport class AppModule {}\n```\n\n---\n\n## Routing\n\n### Protect routes with the guard\n\n```typescript\n// app.routes.ts\nimport { Routes } from \"@angular/router\";\nimport { cognitoAuthGuard, cognitoCallbackResolver } from \"ngx-cognito-auth\";\n\nexport const routes: Routes = [\n  {\n    path: \"callback\",\n    component: CallbackComponent,\n    resolve: { auth: cognitoCallbackResolver }, // handles the OAuth redirect\n  },\n  {\n    path: \"dashboard\",\n    component: DashboardComponent,\n    canActivate: [cognitoAuthGuard], // redirects to Cognito if not authenticated\n  },\n  {\n    path: \"**\",\n    redirectTo: \"dashboard\",\n  },\n];\n```\n\n### Callback component\n\nThe resolver handles everything — the component itself needs no logic:\n\n```typescript\n@Component({\n  standalone: true,\n  template: `\u003cp\u003eSigning in…\u003c/p\u003e`,\n})\nexport class CallbackComponent {}\n```\n\n---\n\n## Using `CognitoAuthService`\n\nInject the service anywhere in your app:\n\n```typescript\nimport { Component, inject } from '@angular/core';\nimport { CognitoAuthService } from 'ngx-cognito-auth';\n\n@Component({ ... })\nexport class MyComponent {\n  private readonly auth = inject(CognitoAuthService);\n}\n```\n\n### Signals\n\n| Signal                   | Type                  | Description                                                                          |\n| ------------------------ | --------------------- | ------------------------------------------------------------------------------------ |\n| `auth.accessToken()`     | `string \\| null`      | Raw JWT access token (Bearer value)                                                  |\n| `auth.user()`            | `CognitoUser \\| null` | Decoded ID token claims                                                              |\n| `auth.isAuthenticated()` | `boolean`             | `true` when an access token or refresh token is present (user has an active session) |\n\n```html\n@if (auth.isAuthenticated()) {\n\u003cp\u003eWelcome, {{ auth.user()?.name }}!\u003c/p\u003e\n} @else {\n\u003cbutton (click)=\"auth.login()\"\u003eSign in\u003c/button\u003e\n}\n```\n\n### Methods\n\n#### `login(returnUrl?: string): Promise\u003cvoid\u003e`\n\nRedirects to the Cognito hosted UI. Optionally pass a `returnUrl` to redirect back after login.\n\n```typescript\nawait this.auth.login(\"/dashboard\");\n```\n\n#### `logout(): void`\n\nClears local tokens and redirects to Cognito's global logout endpoint.\n\n```typescript\nthis.auth.logout();\n```\n\n#### `getToken(): string | null`\n\nReturns the current raw access token synchronously.\n\n```typescript\nconst bearer = this.auth.getToken();\n```\n\n#### `getUser(): CognitoUser | null`\n\nReturns the decoded ID token claims synchronously.\n\n```typescript\nconst user = this.auth.getUser();\n```\n\n#### `refreshTokens(): Promise\u003cvoid\u003e`\n\nSilently refreshes the access and ID tokens using the stored refresh token. Throws if no refresh token is available.\n\n```typescript\ntry {\n  await this.auth.refreshTokens();\n} catch (e) {\n  // refresh token expired or missing — re-login required\n  this.auth.login();\n}\n```\n\n### `CognitoUser` interface\n\n| Claim                | Type      | Description                    |\n| -------------------- | --------- | ------------------------------ |\n| `sub`                | `string`  | Unique user identifier         |\n| `email`              | `string`  | Email address                  |\n| `email_verified`     | `boolean` | Whether the email was verified |\n| `name`               | `string`  | Full name                      |\n| `given_name`         | `string`  | First name                     |\n| `family_name`        | `string`  | Last name                      |\n| `picture`            | `string`  | Profile picture URL            |\n| `phone_number`       | `string`  | Phone number                   |\n| `preferred_username` | `string`  | Preferred username             |\n| `[claim: string]`    | `unknown` | Any custom Cognito attribute   |\n\n---\n\n## HTTP Interceptor\n\n`withCognitoInterceptor()` registers a functional interceptor that:\n\n1. Skips the Cognito `/oauth2/` token endpoint (to prevent loops)\n2. Skips requests that set `SKIP_COGNITO_BEARER` in their context\n3. Attaches `Authorization: Bearer \u003ctoken\u003e` to all other requests\n4. **Automatically refreshes an expired token before the request** — no manual handling required\n\n### Skip Bearer injection for a specific request\n\n```typescript\nimport { HttpContext } from \"@angular/common/http\";\nimport { SKIP_COGNITO_BEARER } from \"ngx-cognito-auth\";\n\nthis.http.get(\"/api/public\", {\n  context: new HttpContext().set(SKIP_COGNITO_BEARER, true),\n});\n```\n\n---\n\n## Token Storage\n\nThe library uses no cookies. All state is stored in the browser's Web Storage APIs.\n\nThe storage key prefix defaults to `cog_auth` and is configurable via `storageKeyPrefix` in `CognitoAuthConfig`.\n\n### `sessionStorage` keys\n\nCleared automatically when the browser tab or window is closed.\n\n| Key                      | Content                               | Set when                       | Cleared when          |\n| ------------------------ | ------------------------------------- | ------------------------------ | --------------------- |\n| `{prefix}_access_token`  | Raw JWT access token (Bearer value)   | Login callback / token refresh | Tab closes · Logout   |\n| `{prefix}_id_token`      | Raw JWT ID token (user claims)        | Login callback / token refresh | Tab closes · Logout   |\n| `{prefix}_pkce_verifier` | Code verifier for auth flow (32-byte) | `login()` is called            | Callback is processed |\n| `{prefix}_pkce_state`    | OAuth state nonce (CSRF protection)   | `login()` is called            | Callback is processed |\n| `{prefix}_return_url`    | App URL to redirect to after login    | `login(returnUrl)` is called   | Callback is processed |\n\n### `localStorage` keys\n\nPersists across tabs and browser restarts.\n\n| Key                      | Content               | Set when                   | Cleared when |\n| ------------------------ | --------------------- | -------------------------- | ------------ |\n| `{prefix}_refresh_token` | Cognito refresh token | Login callback (if issued) | Logout       |\n\n### Notes\n\n- **`sessionStorage`** is tab-scoped — opening the app in a new tab requires a silent refresh (handled automatically by `initialize()`)\n- **`localStorage`** is shared across all tabs of the same origin — the refresh token enables silent re-authentication on the next visit without a full login redirect\n- The access and ID tokens are JWTs and can be decoded client-side; they contain the claims listed in the `CognitoUser` interface\n- The refresh token is opaque — it cannot be decoded and is only valid against the Cognito token endpoint\n\n---\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Copy .env.example to .env and fill in your Cognito values\ncp .env.example .env\n\n# Start the demo app (automatically runs set-env.js first)\nnpm start\n\n# Build the library\nnpm run build:lib\n\n# Build the demo app\nnpm run build:demo\n\n# Run tests\nnpm test\n```\n\n---\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSamsonGross%2Fngx-cognito-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSamsonGross%2Fngx-cognito-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSamsonGross%2Fngx-cognito-auth/lists"}