docs: quickstart changes for v2 (#3906)

* docs: v2 quickstarts

* flutter div

* html

* html

* common https:/[your-domain]-[random-string].zitadel.cloud
This commit is contained in:
Max Peintner 2022-07-07 16:25:56 +02:00 committed by GitHub
parent 252d0fa8b5
commit 91771bc49b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 172 additions and 161 deletions

View File

@ -3,32 +3,32 @@ title: Angular
---
This integration guide shows you the recommended way to integrate ZITADEL into your Angular application.
It shows how to add user login to your application and fetch some data from the user info endpoint.
It shows how to add user login to your application and fetch some data from the user info endpoint.
At the end of the guide, your application has login functionality and has access to the current user's profile.
At the end of the guide, your application has login functionality and has access to the current user's profile.
> This documentation refers to our [example](https://github.com/zitadel/zitadel-examples/tree/main/angular) in GitHub. Note that we've written ZITADEL Console in Angular, so you can also use that as a reference.
> This documentation refers to our [example](https://github.com/zitadel/zitadel-examples/tree/main/angular) in GitHub. Note that we've written ZITADEL Console in Angular, so you can also use that as a reference.
## Setup Application and Get Keys
Before we can start building our application, we have to do a few configuration steps in ZITADEL Console.
You will need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your [Project](https://console.zitadel.ch/projects), then add a new application at the top of the page.
You will need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your Project, then add a new application at the top of the page.
Select Web application type and continue.
We recommend you use [Authorization Code](../../apis/openidoauth/grant-types#authorization-code) in combination with [Proof Key for Code Exchange (PKCE)](../../apis/openidoauth/grant-types#proof-key-for-code-exchange) for all web applications.
We recommend you use [Authorization Code](../../apis/openidoauth/grant-types#authorization-code) in combination with [Proof Key for Code Exchange (PKCE)](../../apis/openidoauth/grant-types#proof-key-for-code-exchange) for all web applications.
![Create app in console](/img/angular/app-create-light.png)
![Create app in console](/img/angular/app-create.png)
### Redirect URIs
With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
With the Redirect URIs field, you tell ZITADEL where it is allowed to redirect users to after authentication. For development, you can set dev mode to `true` to enable insecure HTTP and redirect to a `localhost` URI.
> If you are following along with the [example](https://github.com/zitadel/zitadel-examples/tree/main/angular), set dev mode to `true` and the Redirect URIs to <http://localhost:4200/auth/callback>.
> If you are following along with the [example](https://github.com/zitadel/zitadel-examples/tree/main/angular), set dev mode to `true` and the Redirect URIs to <http://localhost:4200/auth/callback>.
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the Post Logout URIs field.
If you want to redirect the users back to a route on your application after they have logged out, add an optional redirect in the Post Logout URIs field.
Continue and create the application.
### Client ID and Secret
### Client ID
After successful app creation, a pop-up will appear, showing the app's client ID. Copy the client ID, as you will need it to configure your Angular client.
@ -58,7 +58,7 @@ const authConfig: AuthConfig = {
responseType: 'code',
oidc: true,
clientId: 'YOUR-CLIENT-ID', // replace with your appid
issuer: '<YOUR-DOMAIN>', // eg. https://acme-jdo9fs.zitadel.cloud
issuer: 'https:/[your-domain]-[random-string].zitadel.cloud', // replace with your instance
redirectUri: 'http://localhost:4200/auth/callback',
postLogoutRedirectUri: 'http://localhost:4200/signedout', // optional
requireHttps: false // required for running locally
@ -68,14 +68,14 @@ const authConfig: AuthConfig = {
...
imports: [
OAuthModule.forRoot(),
HttpClientModule,
HttpClientModule,
...
providers: [
{
provide: AuthConfig,
useValue: authConfig
}
...
...
```
Set _openid_, _profile_ and _email_ as scope, _code_ as responseType, and oidc to _true_. Then create an authentication service to provide the functions to authenticate your user.
@ -89,63 +89,62 @@ ng g service services/authentication
Copy the following code to your service. This code provides a function `authenticate()` which redirects the user to ZITADEL. After successful login, ZITADEL redirects the user back to the redirect URI configured in _AuthModule_ and ZITADEL Console. Make sure both correspond, otherwise ZITADEL throws an error.
```ts
import { Injectable } from '@angular/core';
import { AuthConfig, OAuthService } from 'angular-oauth2-oidc';
import { BehaviorSubject, from, Observable } from 'rxjs';
import { Injectable } from "@angular/core";
import { AuthConfig, OAuthService } from "angular-oauth2-oidc";
import { BehaviorSubject, from, Observable } from "rxjs";
import { StatehandlerService } from './statehandler.service';
import { StatehandlerService } from "./statehandler.service";
@Injectable({
providedIn: 'root'
providedIn: "root",
})
export class AuthenticationService {
private _authenticated: boolean = false;
private readonly _authenticationChanged: BehaviorSubject<
boolean
> = new BehaviorSubject(this.authenticated);
private _authenticated: boolean = false;
private readonly _authenticationChanged: BehaviorSubject<boolean> =
new BehaviorSubject(this.authenticated);
constructor(
private oauthService: OAuthService,
private authConfig: AuthConfig,
private statehandler: StatehandlerService,
) { }
constructor(
private oauthService: OAuthService,
private authConfig: AuthConfig,
private statehandler: StatehandlerService
) {}
public get authenticated(): boolean {
return this._authenticated;
public get authenticated(): boolean {
return this._authenticated;
}
public get authenticationChanged(): Observable<boolean> {
return this._authenticationChanged;
}
public getOIDCUser(): Observable<any> {
return from(this.oauthService.loadUserProfile());
}
public async authenticate(setState: boolean = true): Promise<boolean> {
this.oauthService.configure(this.authConfig);
this.oauthService.strictDiscoveryDocumentValidation = false;
await this.oauthService.loadDiscoveryDocumentAndTryLogin();
this._authenticated = this.oauthService.hasValidAccessToken();
if (!this.oauthService.hasValidIdToken() || !this.authenticated) {
const newState = setState
? await this.statehandler.createState().toPromise()
: undefined;
this.oauthService.initCodeFlow(newState);
}
this._authenticationChanged.next(this.authenticated);
public get authenticationChanged(): Observable<boolean> {
return this._authenticationChanged;
}
return this.authenticated;
}
public getOIDCUser(): Observable<any> {
return from(this.oauthService.loadUserProfile());
}
public async authenticate(
setState: boolean = true,
): Promise<boolean> {
this.oauthService.configure(this.authConfig);
this.oauthService.strictDiscoveryDocumentValidation = false;
await this.oauthService.loadDiscoveryDocumentAndTryLogin();
this._authenticated = this.oauthService.hasValidAccessToken();
if (!this.oauthService.hasValidIdToken() || !this.authenticated) {
const newState = setState ? await this.statehandler.createState().toPromise() : undefined;
this.oauthService.initCodeFlow(newState);
}
this._authenticationChanged.next(this.authenticated);
return this.authenticated;
}
public signout(): void {
this.oauthService.logOut();
this._authenticated = false;
this._authenticationChanged.next(false);
}
public signout(): void {
this.oauthService.logOut();
this._authenticated = false;
this._authenticationChanged.next(false);
}
}
```
@ -215,26 +214,35 @@ ng g guard guards/auth
This code shows the _AuthGuard_ used in ZITADEL Console.
```ts
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthenticationService } from '../services/authentication.service';
import { Injectable } from "@angular/core";
import {
ActivatedRouteSnapshot,
CanActivate,
RouterStateSnapshot,
UrlTree,
} from "@angular/router";
import { Observable } from "rxjs";
import { AuthenticationService } from "../services/authentication.service";
@Injectable({
providedIn: 'root'
providedIn: "root",
})
export class AuthGuard implements CanActivate {
constructor(private auth: AuthenticationService) {}
constructor(private auth: AuthenticationService) { }
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (!this.auth.authenticated) {
return this.auth.authenticate();
}
return this.auth.authenticated;
}
state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
if (!this.auth.authenticated) {
return this.auth.authenticate();
}
return this.auth.authenticated;
}
}
```
@ -267,14 +275,14 @@ const routes: Routes = [
Call `auth.signout()` for logging the current user out. Note that you can also configure a logout redirect URI if you want your users to be redirected after logout.
```ts
import { AuthenticationService } from 'src/app/services/authentication.service';
import { AuthenticationService } from "src/app/services/authentication.service";
export class SomeComponentWithLogout {
constructor(private authService: AuthenticationService){}
constructor(private authService: AuthenticationService) {}
public signout(): Promise<void> {
return this.authService.signout();
}
public signout(): Promise<void> {
return this.authService.signout();
}
}
```
@ -297,7 +305,7 @@ And in your HTML file:
```html
<div *ngIf="user$ | async as user">
<p>{{user | json}}</p>
<p>{{user | json}}</p>
</div>
```

View File

@ -45,14 +45,14 @@ You may want to change the Flutter SDK version in `pubspec.yaml` from
```yaml
environment:
sdk: '>=2.7.0 <3.0.0'
sdk: ">=2.7.0 <3.0.0"
```
to
```yaml
environment:
sdk: '>=2.12.0 <3.0.0'
sdk: ">=2.12.0 <3.0.0"
```
With this, you'll enable "nullable by default" mode in Flutter, as well as new language features.
@ -257,7 +257,7 @@ Future<void> _authenticate() async {
AuthorizationTokenRequest(
'<<CLIENT_ID>>', // Client ID of the native application
'<<CALLBACK_URL>>', // The registered url from zitadel (e.g. ch.myexample.app://signin)
issuer: '<<ISSUER>>', // most of the cases: https://issuer.zitadel.ch
issuer: '<<ISSUER>>', // most of the cases: https:/[your-domain]-[random-string].zitadel.cloud
scopes: [
'openid',
'profile',
@ -268,7 +268,7 @@ Future<void> _authenticate() async {
);
final userInfoResponse = await get(
Uri.parse('https://api.zitadel.ch/oauth/v2/userinfo'),
Uri.parse('https://[your-instance].zitadel.cloud/oauth/v2/userinfo'),
headers: {
HttpHeaders.authorizationHeader: 'Bearer ${result.accessToken}',
HttpHeaders.acceptHeader: 'application/json; charset=UTF-8'
@ -333,7 +333,7 @@ class _MyHomePageState extends State<MyHomePage> {
);
final userInfoResponse = await get(
Uri.parse('https://api.zitadel.ch/oauth/v2/userinfo'),
Uri.parse('https:/[your-domain]-[random-string].zitadel.cloud/oauth/v2/userinfo'), // replace with your instance
headers: {
HttpHeaders.authorizationHeader: 'Bearer ${result.accessToken}',
HttpHeaders.acceptHeader: 'application/json; charset=UTF-8'
@ -407,10 +407,7 @@ class _MyHomePageState extends State<MyHomePage> {
If you run this application, you can authenticate with a valid ZITADEL user.
<div style={{display:'flex', 'justify-content': 'center'}}>
<div style={{display:'flex', 'align-items': 'center'}}>
<div style={{display: 'grid', 'grid-column-gap': '1rem', 'grid-template-columns': '1fr 1fr'}}>
<img src="/img/flutter/not-authed.png" alt="Unauthenticated" height="500px" />
<span style={{padding:'1rem'}}>becomes</span>
<img src="/img/flutter/authed.png" alt="Flutter Authenticated" height="500px" />
</div>
</div>

View File

@ -40,47 +40,47 @@ NextAuth.js exposes a REST API which is used by your client.
To setup your configuration, create a file called [...nextauth].tsx in `pages/api/auth`.
```ts
import NextAuth from 'next-auth';
import NextAuth from "next-auth";
export const ZITADEL = {
id: "zitadel",
name: "zitadel",
type: "oauth",
version: "2.0",
scope: "openid profile email",
params: { response_type: "code", grant_type: "authorization_code" },
authorizationParams: { grant_type: "authorization_code", response_type: "code" },
accessTokenUrl: "https://api.zitadel.dev/oauth/v2/token",
requestTokenUrl: "https://api.zitadel.dev/oauth/v2/token",
authorizationUrl: "https://accounts.zitadel.dev/oauth/v2/authorize",
profileUrl: "https://api.zitadel.dev/oauth/v2/userinfo",
protection: "pkce",
async profile(profile, tokens) {
console.log(profile, tokens);
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture
};
},
clientId: process.env.ZITADEL_CLIENT_ID,
session: {
jwt: true,
id: "zitadel",
name: "zitadel",
type: "oauth",
version: "2",
wellKnown: process.env.ZITADEL_ISSUER,
authorization: {
params: {
scope: "openid email profile",
},
},
idToken: true,
checks: ["pkce", "state"],
client: {
token_endpoint_auth_method: "none",
},
async profile(profile) {
return {
id: profile.sub,
name: profile.name,
firstName: profile.given_name,
lastName: profile.family_name,
email: profile.email,
loginName: profile.preferred_username,
image: profile.picture,
};
},
clientId: process.env.ZITADEL_CLIENT_ID,
};
export default NextAuth({
providers: [
ZITADEL
],
providers: [ZITADEL],
});
```
Replace the endpoints `https://api.zitadel.dev/` with `https://api.zitadel.ch/` if your using a ZITADEL CLOUD tier or your own endpoint if your using a self hosted ENTERPRISE tier respectively.
Replace the endpoints `https:/[your-domain]-[random-string].zitadel.cloud` with your instance or if your using a ZITADEL CLOUD tier or your own endpoint if your using a self hosted ENTERPRISE tier respectively.
We recommend using the Authentication Code flow secured by PKCE for the Authentication flow.
To be able to connect to ZITADEL, navigate to your [Console Projects](https://console.zitadel.ch/projects) create or select an existing project and add your app selecting WEB, then PKCE, and then add `http://localhost:3000/api/auth/callback/zitadel` as redirect url to your app.
To be able to connect to ZITADEL, navigate to your Console Projects, create or select an existing project and add your app selecting WEB, then PKCE, and then add `http://localhost:3000/api/auth/callback/zitadel` as redirect url to your app.
For simplicity reasons we set the default to the one that next-auth provides us. You'll be able to change the redirect later if you want to.
@ -95,6 +95,7 @@ Create a file `.env` in the root of the project and add the following keys to it
```
NEXTAUTH_URL=http://localhost:3000
ZITADEL_CLIENT_ID=[yourClientId]
ZITADEL_ISSUER=https:/[your-domain]-[random-string].zitadel.cloud
```
# User interface
@ -107,7 +108,7 @@ Note that signIn method requires the id of the provider we provided earlier, and
import { signIn, signOut, useSession } from 'next-auth/client';
export default function Page() {
const [session, loading] = useSession();
const { data: session } = useSession();
...
{!session && <>
Not signed in <br />
@ -129,13 +130,14 @@ To allow session state to be shared between pages - which improves performance,
Take a loot at the template `_app.tsx`.
```ts
import { Provider } from 'next-auth/client';
import { SessionProvider } from "next-auth/react";
function MyApp({ Component, pageProps }) {
return <Provider
session={pageProps.session} >
<Component {...pageProps} />
</Provider>;
return (
<SessionProvider session={pageProps.session}>
<Component {...pageProps} />
</SessionProvider>
);
}
export default MyApp;
@ -143,17 +145,19 @@ export default MyApp;
Last thing: create a `profile.tsx` in /pages which renders the callback page.
## Learn More
```ts
import Link from "next/link";
To learn more about Next.js, take a look at the following resources:
import styles from "../styles/Home.module.css";
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
export default function Profile() {
return (
<div className={styles.container}>
<h1>Login successful</h1>
<Link href="/">
<button>Back to Home</button>
</Link>
</div>
);
}
```

View File

@ -10,7 +10,7 @@ At the end of the guide you should have an application able to login a user and
## Setup Application and get Keys
Before we can start building our application we have to do a few configuration steps in ZITADEL Console.
You will need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your [Project](https://console.zitadel.ch/projects) and add a new application at the top of the page.
You will need to provide some information about your app. We recommend creating a new app to start from scratch. Navigate to your Project and add a new application at the top of the page.
Select User Agent and continue. More about the different app types can you find [here](https://docs.zitadel.com/docs/guides/authorization/oauth-recommended-flows#different-client-profiles).
We recommend that you use [Authorization Code](../../apis/openidoauth/grant-types#authorization-code) in combination with [Proof Key for Code Exchange](../../apis/openidoauth/grant-types#proof-key-for-code-exchange) for all web applications.
@ -54,38 +54,40 @@ This library helps integrating ZITADEL Authentication in your React Application.
With the installed oidc pakage you will need an AuthProvider which should contain the OIDC configuration.
The oidc configuration should contain **openid**, **profile** and **email** as scope and **code** as responseType.
In the code below the authority is already set to the issuer of zitadel.ch you can find this in the ZITADEL Console on you application.
In the code below make sure to change the issuer to your instance url. You can find this in the ZITADEL Console on you application.
Replace the clientId value 'YOUR-CLIENT-ID' with the generated client id of you application in ZITADEL Console.
```ts
import React from 'react';
import { AuthProvider } from 'oidc-react';
import './App.css';
import React from "react";
import { AuthProvider } from "oidc-react";
import "./App.css";
const oidcConfig = {
onSignIn: async (response: any) => {
alert('You logged in :' + response.profile.given_name + ' ' + response.profile.family_name);
window.location.hash = '';
},
authority: 'https://issuer.zitadel.ch',
clientId:
'YOUR-CLIENT-ID',
responseType: 'code',
redirectUri: 'http://localhost:3000/',
scope: 'openid profile email'
onSignIn: async (response: any) => {
alert(
"You logged in :" +
response.profile.given_name +
" " +
response.profile.family_name
);
window.location.hash = "";
},
authority: "https:/[your-domain]-[random-string].zitadel.cloud", // replace with your instance
clientId: "YOUR-CLIENT-ID",
responseType: "code",
redirectUri: "http://localhost:3000/",
scope: "openid profile email",
};
function App() {
return (
<AuthProvider {...oidcConfig}>
<div className="App">
return (
<AuthProvider {...oidcConfig}>
<div className="App">
<header className="App-header">
<p>Hello World</p>
</header>
</div>
<p>Hello World</p>
</header>
</div>
</AuthProvider>
);
);
}
export default App;
@ -100,7 +102,7 @@ npm start
```
Your browser should automatically open the app site or just go to `http://localhost:3000/`.
On opening the app in the browser you will be redirected to the login of zitadel.ch
On opening the app in the browser you will be redirected to the login of your instance.
After successfully authenticating your user, you will get back to you application.
It should show a popup which says: **You logged in {FirstName} {LastName}**

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

BIN
docs/static/img/angular/app-create.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB