diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ad3b3d3 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,61 @@ +name: Publish + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + OIDC_ISSUER: "https://testid.cerberauth.com" + +jobs: + deploy-nodejs-cloudflare: + runs-on: ubuntu-latest + + defaults: + run: + shell: bash + working-directory: ${{ matrix.workingDirectory }} + + strategy: + matrix: + include: + - workingDirectory: ./examples/react-spa + projectName: cerberauth-react-spa-oidc + directory: ./dist + - workingDirectory: ./examples/angular-spa + projectName: cerberauth-angular-spa-oidc + directory: ./dist/angular-spa/browser + + permissions: + contents: read + deployments: write + + steps: + - name: Checkout 🛎 + uses: actions/checkout@v4 + + - name: Setup node env 🏗 + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: 'npm' + cache-dependency-path: '${{ matrix.workingDirectory }}/package-lock.json' + + - name: Install dependencies 👨🏻‍💻 + run: npm ci + + - name: Run build + run: npm run build + + - name: Publish + uses: cloudflare/pages-action@1 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + projectName: ${{ matrix.projectName }} + directory: ${{ matrix.workingDirectory }}/${{ matrix.directory }} + gitHubToken: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 1da01de..485f302 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OpenID Connect Examples / Demo -This repository contains a collection of OpenID Connect examples and demos. +This repository contains a collection of OpenID Connect examples. ## Examples diff --git a/examples/angular-spa/README.md b/examples/angular-spa/README.md index e5e5643..5442252 100644 --- a/examples/angular-spa/README.md +++ b/examples/angular-spa/README.md @@ -1,27 +1,76 @@ -# AngularSpa +# Angular SPA (Single Page App) using Authorization Code Flow with PKCE -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 18.0.3. +This project demonstrates how to implement the Authorization Code Flow with PKCE for an Angular SPA. -## Development server +Disclaimer: This project is for educational purposes only and should not be used in production without proper security review and testing. -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. +## Deployment -## Code scaffolding +This project is deployed on Cloudflare Pages. You can access the live demo [here](https://cerberauth-angular-spa-oidc.pages.dev/). -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. +## Prerequisites -## Build +Before getting started, make sure you have the following: -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. +- Node.js installed on your machine +- An OpenID Connect provider that supports the Authorization Code Flow with PKCE -## Running unit tests +## Getting Started -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). +1. Clone the repository: -## Running end-to-end tests + ```bash + git clone https://github.com/cerberauth/openid-connect-examples.git + ``` -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. +2. Install the dependencies: -## Further help + ```bash + cd openid-connect-examples/angular-spa + npm ci + ``` -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page. +3. Configure the OpenID Connect provider: + +If you don't have an OpenID Connect provider, you can use [TestID OpenID Connect Provider](https://testid.cerberauth.com/). + + - Obtain the client ID and client secret from your OpenID Connect provider. + - Register the redirect URI for your React SPA in the provider's developer console. + +4. Update the configuration: + + - Update the `environment.ts` file in the `src/environments` directory. + - Add the necessary environment variables to the `environment.ts` file. For example: + + ```typescript + export const environment = { + production: false, + clientId: 'your-client-id', + redirectUri: 'http://localhost:4200/callback', + issuer: 'https://testid.cerberauth.com', + scopes: 'openid profile email', + }; + ``` + + Replace `your-client-id`, `http://localhost:4200/callback`, and `https://testid.cerberauth.com` with the actual values provided by your OpenID Connect provider. + +5. Start the development server: + + ```bash + npm start + ``` + +6. Open your browser and navigate to `http://localhost:4200/`. + +7. Click on the "Login" button to initiate the authorization code flow. + +8. After successful authentication, you will be redirected back to the React SPA and the user information will be displayed. + +## Additional Resources + +- [angular-oauth2-oidc](https://github.com/manfredsteyer/angular-oauth2-oidc) +- [OpenID Connect](https://openid.net/) +- [OAuth 2.0 Authorization Code Flow](https://oauth.net/2/grant-types/authorization-code/) +- [PKCE](https://oauth.net/2/pkce/) +- [Awesome OpenID Connect](https://github.com/cerberauth/awesome-openid-connect) +- [Angular](https://angular.io/) diff --git a/examples/angular-spa/src/app/app.component.html b/examples/angular-spa/src/app/app.component.html index 3a25808..ac6fd90 100644 --- a/examples/angular-spa/src/app/app.component.html +++ b/examples/angular-spa/src/app/app.component.html @@ -1,23 +1,40 @@
-
-
-

Welcome to {{ title }}!

-
+
+
+

+ Angular SPA Example using OpenID Connect +

+

+ This example demonstrates how to authenticate users in a Angular Single Page Application (SPA) using OpenID + Connect Protocol. +

-

User

-

{{ userName }}

+ + + + -

Id-Token

-

{{ idToken }}

+

+ If you want to checkout out how to implement OpenID Connect in your Angular SPA, take a look at the source code. +

+
-

Access Token

-

{{ accessToken }}

- -

- -

+
diff --git a/examples/angular-spa/src/app/app.component.ts b/examples/angular-spa/src/app/app.component.ts index ccbda96..28e0f95 100644 --- a/examples/angular-spa/src/app/app.component.ts +++ b/examples/angular-spa/src/app/app.component.ts @@ -18,33 +18,23 @@ export class AppComponent { constructor(private oauthService: OAuthService) { this.oauthService.configure(environment.auth); - this.oauthService.loadDiscoveryDocumentAndLogin({ customHashFragment: window.location.search }); - this.oauthService.setupAutomaticSilentRefresh(); + this.oauthService.loadDiscoveryDocumentAndTryLogin({ customHashFragment: window.location.search }); this.oauthService.events .pipe(filter((e) => e.type === 'token_received')) .subscribe((_) => this.oauthService.loadUserProfile()); } - get userName(): string | null { - const claims = this.oauthService.getIdentityClaims(); - if (!claims) { - return null; - } - - return claims['name']; - } - - get idToken(): string { - return this.oauthService.getIdToken(); + login() { + this.oauthService.initLoginFlow(); } - get accessToken(): string { - return this.oauthService.getAccessToken(); + logout() { + this.oauthService.logOut(); } - refresh() { - this.oauthService.refreshToken(); + get user() { + return this.oauthService.getIdentityClaims(); } } diff --git a/examples/angular-spa/src/environments/environment.development.ts b/examples/angular-spa/src/environments/environment.development.ts index 12a4e2d..194bcaa 100644 --- a/examples/angular-spa/src/environments/environment.development.ts +++ b/examples/angular-spa/src/environments/environment.development.ts @@ -3,7 +3,7 @@ export const environment = { auth: { issuer: 'https://testid.cerberauth.com', redirectUri: window.location.origin + '/index.html', - clientId: '', + clientId: '8f39ed37-ca04-464b-9d65-8aece2e46518', responseType: 'code', scope: 'openid profile email', diff --git a/examples/angular-spa/src/environments/environment.ts b/examples/angular-spa/src/environments/environment.ts index c54336e..bb8b4cb 100644 --- a/examples/angular-spa/src/environments/environment.ts +++ b/examples/angular-spa/src/environments/environment.ts @@ -3,7 +3,7 @@ export const environment = { auth: { issuer: 'https://testid.cerberauth.com', redirectUri: window.location.origin + '/index.html', - clientId: '', + clientId: '8f39ed37-ca04-464b-9d65-8aece2e46518', responseType: 'code', scope: 'openid profile email', diff --git a/examples/react-spa/.env b/examples/react-spa/.env index d9242a1..f2b2ae1 100644 --- a/examples/react-spa/.env +++ b/examples/react-spa/.env @@ -1,2 +1,2 @@ -VITE_OIDC_ISSUER="" -VITE_OIDC_CLIENT_ID="" +VITE_OIDC_ISSUER="https://testid.cerberauth.com" +VITE_OIDC_CLIENT_ID="c6c0c0ec-09e0-448e-a856-3e596c3bdd9d" diff --git a/examples/react-spa/README.md b/examples/react-spa/README.md index 8018b6c..b7ffecb 100644 --- a/examples/react-spa/README.md +++ b/examples/react-spa/README.md @@ -4,6 +4,10 @@ This project demonstrates how to implement the Authorization Code Flow with PKCE Disclaimer: This project is for educational purposes only and should not be used in production without proper security review and testing. +## Deployment + +This project is deployed on Cloudflare Pages. You can access the live demo [here](https://cerberauth-react-spa-oidc.pages.dev/). + ## Prerequisites Before getting started, make sure you have the following: @@ -22,12 +26,14 @@ Before getting started, make sure you have the following: 2. Install the dependencies: ```bash - cd openid-connect-examples/react-spa-authorization-code-flow - npm install + cd openid-connect-examples/react-spa + npm ci ``` 3. Configure the OpenID Connect provider: +If you don't have an OpenID Connect provider, you can use [TestID OpenID Connect Provider](https://testid.cerberauth.com/). + - Obtain the client ID and client secret from your OpenID Connect provider. - Register the redirect URI for your React SPA in the provider's developer console. @@ -59,6 +65,7 @@ Before getting started, make sure you have the following: ## Additional Resources +- [oauth4webapi](https://github.com/panva/oauth4webapi) - [OpenID Connect](https://openid.net/) - [OAuth 2.0 Authorization Code Flow](https://oauth.net/2/grant-types/authorization-code/) - [PKCE](https://oauth.net/2/pkce/) diff --git a/examples/react-spa/src/App.tsx b/examples/react-spa/src/App.tsx index 0761d57..b5cd2c2 100644 --- a/examples/react-spa/src/App.tsx +++ b/examples/react-spa/src/App.tsx @@ -1,7 +1,6 @@ import { Router } from 'wouter' import { AuthProvider } from './lib/auth/AuthProvider' -import { Header } from './components/Header' import { PageRouter } from './components/PageRouter' function App() { @@ -11,13 +10,7 @@ function App() { clientId={import.meta.env.VITE_OIDC_CLIENT_ID} > -
-
-
- - -
-
+
) diff --git a/examples/react-spa/src/components/Button.tsx b/examples/react-spa/src/components/Button.tsx new file mode 100644 index 0000000..4a2521c --- /dev/null +++ b/examples/react-spa/src/components/Button.tsx @@ -0,0 +1,14 @@ +export interface ButtonProps extends React.ButtonHTMLAttributes { + children: React.ReactNode +} + +export const Button: React.FC = ({ children, ...props }) => { + return ( + + ) +} diff --git a/examples/react-spa/src/components/Header.tsx b/examples/react-spa/src/components/Header.tsx deleted file mode 100644 index 22936eb..0000000 --- a/examples/react-spa/src/components/Header.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react' -import { useAuth } from '../lib/auth/useAuth' - -export const Header: React.FC = () => { - const { isAuthenticated, login, logout, user } = useAuth() - - return ( -
-
-

My App

-
-
- {isAuthenticated ? ( - <> - {user?.picture && ( - Profile - )} - - - ) : ( - <> - - {/* */} - - )} -
-
- ); -}; diff --git a/examples/react-spa/src/pages/home.tsx b/examples/react-spa/src/pages/home.tsx index 93fa80b..6abc711 100644 --- a/examples/react-spa/src/pages/home.tsx +++ b/examples/react-spa/src/pages/home.tsx @@ -1,7 +1,37 @@ +import { Button } from '../components/Button' +import { useAuth } from '../lib/auth/useAuth' + export function Home() { + const { login, logout, isAuthenticated } = useAuth() + return ( -
-

Welcome to the home page

+
+
+

+ React SPA Example using OpenID Connect +

+

+ This example demonstrates how to authenticate users in a React Single Page Application (SPA) using OpenID Connect Protocol. +

+ {isAuthenticated ? ( + + ) : ( + + )} +

+ If you want to checkout out how to implement OpenID Connect in your React SPA, take a look at the source code. +

+
+ +
) }