@webda/google-auth 4.0.0-beta.3 → 4.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,91 +15,94 @@ This module is part of Webda Application Framework that allows you to quickly de
15
15
 
16
16
  # @webda/google-auth
17
17
 
18
- > Google OAuth 2.0 authentication provider for Webda — adds `GET /auth/google` and callback handling to your application so users can sign in with their Google account.
18
+ > "Sign in with Google" (OpenID Connect) provider for [`@webda/auth`](../auth): adds `GET /auth/google`, its callback
19
+ > and the `Auth.Google.Token` operation; logins go through the `Authentication` service (linking, registration,
20
+ > sessions, tokens).
19
21
 
20
22
  ## When to use it
21
23
 
22
- - You want to add "Sign in with Google" to a Webda application without hand-rolling OAuth flows.
23
- - You need an offline access token (e.g. for server-side Google API calls on behalf of the user).
24
- - You are building a multi-provider auth system alongside other `@webda/oauth` providers.
24
+ - You want users to sign in with their Google account, in the browser or from a mobile/desktop client holding a
25
+ Google ID token.
26
+ - You want to restrict logins to a Google Workspace domain (`hostedDomain`).
27
+ - You need an offline Google refresh token (`access_type: "offline"`; stored in the ident tokens).
25
28
 
26
29
  ## Install
27
30
 
28
31
  ```bash
29
- pnpm add @webda/google-auth
32
+ pnpm add @webda/auth @webda/google-auth
30
33
  ```
31
34
 
32
35
  ## Configuration
33
36
 
34
- ```json
37
+ `GoogleAuthentication` is a provider service next to `Authentication` (see the
38
+ [Authentication guide](https://docs.webda.io/Security/Authentication)):
39
+
40
+ ```jsonc
35
41
  {
36
42
  "services": {
37
- "Authentication": {
38
- "type": "Authentication",
39
- "providers": {
40
- "google": {
41
- "type": "GoogleAuthentication",
42
- "client_id": "${GOOGLE_CLIENT_ID}",
43
- "client_secret": "${GOOGLE_CLIENT_SECRET}",
44
- "access_type": "online",
45
- "redirect_uri": "https://myapp.example.com/auth/google/callback"
46
- }
47
- }
43
+ "Authentication": { "type": "Webda/Authentication" },
44
+ "google": {
45
+ "type": "Webda/GoogleAuthentication",
46
+ "client_id": "${GOOGLE_CLIENT_ID}",
47
+ "client_secret": "${GOOGLE_CLIENT_SECRET}",
48
+ // Register exactly this url in the Google Cloud console; set it explicitly behind a proxy
49
+ "redirect_uri": "https://api.example.com/auth/google/callback",
50
+ "redirects": {
51
+ "success": "https://app.example.com/", // default "/"
52
+ "failure": "https://app.example.com/login" // required, receives ?reason=CODE
53
+ },
54
+ // Allowed targets of GET /auth/google?redirect=... (same origin, this path or below)
55
+ "authorized_uris": ["https://app.example.com/"],
56
+ "audiences": ["1234-ios.apps.googleusercontent.com"], // other client ids accepted by Auth.Google.Token
57
+ "hostedDomain": "example.com" // optional: Google Workspace accounts of this domain only
48
58
  }
49
59
  }
50
60
  }
51
61
  ```
52
62
 
53
- | Parameter | Type | Default | Required | Description |
54
- |---|---|---|---|---|
55
- | `client_id` | string | — | Yes | Google OAuth 2.0 Client ID from Google Cloud Console |
56
- | `client_secret` | string | — | Yes | Google OAuth 2.0 Client Secret |
57
- | `access_type` | `"online"` \| `"offline"` | `"online"` | No | `"offline"` returns a refresh token for server-side API access |
58
- | `project_id` | string | — | No | Google Cloud Project ID (informational) |
59
- | `auth_options` | object | — | No | Additional parameters forwarded to the Google authorization URL |
60
- | `redirects.use_referer` | boolean | — | No | Redirect to the HTTP Referer after successful login |
61
- | `redirects.whitelist` | string[] | — | No | Allowed redirect URLs (regexp strings) |
63
+ | Parameter | Default | Description |
64
+ | ----------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------- |
65
+ | `client_id`, `client_secret` | required | OAuth client of type "Web application" |
66
+ | `url` | `/auth/google` | Prefix of the login and callback routes |
67
+ | `redirect_uri` | request url + `/callback` | Callback url sent to Google |
68
+ | `redirects.success` / `redirects.failure` | `/` / required | Where the callback redirects |
69
+ | `authorized_uris` | `[]` | Allowed `redirect` parameters (absolute urls) |
70
+ | `scope` | `["openid", "email", "profile"]` | Requested scopes (`openid` is needed for the ID token) |
71
+ | `access_type` | `"online"` | `"offline"` also returns a refresh token |
72
+ | `audiences` | `[]` | Extra client ids accepted by `Auth.Google.Token` |
73
+ | `hostedDomain` | - | Required `hd` claim; refused with `EMAIL_DOMAIN_NOT_ALLOWED` |
74
+ | `auth_options` | - | Extra authorization url parameters (`prompt`, `login_hint`...); cannot override the flow fields |
75
+ | `allowedEmailDomains`, `trustEmailVerification` | - | Per-provider email policy of `@webda/auth` |
62
76
 
63
77
  ## Usage
64
78
 
79
+ - Browser: link to `GET /auth/google?redirect=https://app.example.com/after`. The flow uses PKCE and an OpenID nonce,
80
+ kept in a short-lived encrypted `webda_oauth_google` cookie (so it also works with a `SameSite=Strict` session
81
+ cookie). After the Google consent the callback logs the user in and redirects to `redirect` (or
82
+ `redirects.success`), adding `?mfa=required` when the user still has to pass MFA. Failures redirect to
83
+ `redirects.failure?reason=CODE` (`STATE_MISMATCH`, `PROVIDER_ERROR`, `TOKEN_INVALID`, `ACCOUNT_EXISTS`,
84
+ `EMAIL_DOMAIN_NOT_ALLOWED`, ...).
85
+ - Other clients: `POST /auth/google/token` (`Auth.Google.Token`) with a JSON body `{ "token": "<Google ID token>" }`
86
+ or the v3 body `{ "tokens": { "id_token": "...", "access_token": "...", ... } }` returns the `@webda/auth` result
87
+ (`{ status: "ok", accessToken, refreshToken, ... }`). Only ID tokens are verified; access tokens alone are refused.
88
+ This operation never links the identity to an already logged-in user.
89
+
90
+ The Google identity is the ID token `sub`; the email is only treated as verified when `email_verified` is `true`.
91
+ Google credentials are stored encrypted on the ident (`await ident.tokens.get()`) and published after each login:
92
+
65
93
  ```typescript
66
- // 1. Register your OAuth credentials in Google Cloud Console:
67
- // APIs & Services > Credentials > Create OAuth 2.0 Client ID
68
- // Authorized redirect URI: https://myapp.example.com/auth/google/callback
69
-
70
- // 2. Configure (see above). The framework auto-registers these routes:
71
- // GET /auth/google → redirects to Google consent screen
72
- // GET /auth/google/callback → handles the OAuth callback, creates a session
73
-
74
- // 3. Listen to the auth event to customize post-login behaviour:
75
- import { GoogleAuthentication } from "@webda/google-auth";
76
- import { Bean, Inject } from "@webda/core";
77
-
78
- @Bean
79
- export class ProfileSync extends Service {
80
- @Inject("Authentication")
81
- auth: any;
82
-
83
- async resolve(): Promise<this> {
84
- await super.resolve();
85
- // Fired after a successful Google login
86
- this.auth.on("GoogleAuth.Tokens", async ({ tokens, context }) => {
87
- // tokens.access_token, tokens.refresh_token (if access_type=offline)
88
- const user = context.getCurrentUser();
89
- // ... sync Google profile data to your User model
90
- });
91
- return this;
92
- }
93
- }
94
+ useService("google").on("GoogleAuth.Tokens", async ({ tokens, context }) => {
95
+ // tokens.access_token, tokens.refresh_token (access_type "offline")
96
+ });
94
97
  ```
95
98
 
96
99
  ## Reference
97
100
 
98
- - API reference: see the auto-generated typedoc at `docs/pages/Modules/google-auth/`.
99
101
  - Source: [`packages/google-auth`](https://github.com/loopingz/webda.io/tree/main/packages/google-auth)
100
- - Related: [`@webda/core`](../core) Authentication service; [`@webda/gcp`](../gcp) for Cloud-side GCP integrations.
102
+ - Related: [`@webda/auth`](../auth) (`OAuthProvider` base class, `Authentication` service).
101
103
 
102
104
  <!-- README_FOOTER -->
105
+
103
106
  ## Sponsors
104
107
 
105
108
  <!--
@@ -1,136 +1,125 @@
1
- import { EventWithContext, OAuthEvents, OAuthService, OAuthServiceParameters, RequestFilter, WebContext } from "@webda/core";
2
- import { Credentials, OAuth2Client } from "google-auth-library";
3
- export interface EventGoogleOAuthToken extends EventWithContext<WebContext> {
1
+ import { type AuthResult, type EventWithContext, type ResolvedIdentity } from "@webda/core";
2
+ import { type OAuthAuthorizationRequest, type OAuthCallbackRequest, OAuthProvider, OAuthProviderParameters, type OAuthTokenRequest } from "@webda/auth";
3
+ import { type Credentials, OAuth2Client, type TokenPayload } from "google-auth-library";
4
+ /** Emitted with the Google credentials of a successful login */
5
+ export interface EventGoogleOAuthToken extends EventWithContext {
4
6
  /**
5
- * Tokens retrieved from Google
7
+ * Credentials: from the code exchange (browser flow), or as sent to `Auth.Google.Token` (`tokens`, or
8
+ * `{ id_token }` for a bare token). Only the ID token is verified: treat the other values as client-provided on
9
+ * the token operation
6
10
  */
7
11
  tokens: Credentials;
8
12
  }
13
+ /** Events of GoogleAuthentication */
14
+ export type GoogleAuthEvents = {
15
+ "GoogleAuth.Tokens": EventGoogleOAuthToken;
16
+ };
9
17
  /**
10
- * Credentials to manage Google Auth
11
- * https://developers.google.com/identity/protocols/oauth2
18
+ * Google login parameters
19
+ * https://developers.google.com/identity/protocols/oauth2/openid-connect
12
20
  */
13
- export declare class GoogleParameters extends OAuthServiceParameters {
21
+ export declare class GoogleParameters extends OAuthProviderParameters {
14
22
  /**
15
- * Google Auth Client id
23
+ * Google OAuth client id (web application)
16
24
  */
17
25
  client_id: string;
18
26
  /**
19
- * Google Auth Client secret
27
+ * Google OAuth client secret
20
28
  */
21
29
  client_secret: string;
22
30
  /**
23
- * Google Project ID
31
+ * Scopes requested from Google
32
+ * @default ["openid", "email", "profile"]
24
33
  */
25
- project_id?: string;
34
+ scope?: string[];
26
35
  /**
27
- * Type of access for Google token
28
- *
29
- * online by default
36
+ * Type of access: "offline" also returns a refresh token (stored encrypted in the ident tokens)
37
+ * @default "online"
30
38
  */
31
39
  access_type?: "online" | "offline";
32
- auth_options?: any;
33
- redirects?: {
34
- use_referer: boolean;
35
- whitelist: string[];
36
- defaults: {
37
- [key: string]: string;
38
- };
39
- };
40
- /**
41
- * Load parameters with Google defaults
42
- * @param params - the service parameters
43
- * @returns this
44
- */
45
- load(params?: any): this;
46
- }
47
- type GoogleAuthEvents = OAuthEvents & {
48
- "GoogleAuth.Tokens": EventGoogleOAuthToken;
49
- };
50
- /**
51
- * Manage Google Authentication
52
- *
53
- * @WebdaModda
54
- */
55
- export default class GoogleAuthentication<T extends GoogleParameters = GoogleParameters> extends OAuthService<T, GoogleAuthEvents> implements RequestFilter<WebContext> {
56
- protected _client: OAuth2Client;
57
40
  /**
58
- * Return provider name
59
- * @returns the provider name
41
+ * Other client ids whose ID tokens `Auth.Google.Token` accepts (for example Android/iOS client ids)
42
+ * @default []
60
43
  */
61
- getName(): string;
44
+ audiences?: string[];
62
45
  /**
63
- * Allow every accounts.google.
64
- * @returns the referer patterns allowed to call back
46
+ * Only accept Google Workspace accounts of this domain (the `hd` claim of the ID token); also sent as a hint to
47
+ * the account chooser
65
48
  */
66
- getCallbackReferer(): RegExp[];
49
+ hostedDomain?: string;
67
50
  /**
68
- * Get OAuth callback query parameters
69
- * @returns the callback query parameters
51
+ * Additional authorization url parameters (for example `prompt`, `login_hint`); cannot override `state`,
52
+ * `redirect_uri`, `scope`, `access_type`, `response_type`, `code_challenge*`, `nonce` nor `hd`
53
+ * See https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters
70
54
  */
71
- getCallbackQueryParams(): {
72
- name: string;
73
- required: boolean;
74
- }[];
55
+ auth_options?: Record<string, any>;
75
56
  /**
76
- * Expose on /google by default
77
- * @returns the default url
57
+ * @param params - raw parameters
58
+ * @returns this
78
59
  */
79
- getDefaultUrl(): string;
60
+ load(params?: any): this;
61
+ }
62
+ /**
63
+ * Sign in with Google (OpenID Connect)
64
+ *
65
+ * The browser flow (`GET /auth/google`, `GET /auth/google/callback`) uses PKCE and a nonce, exchanges the code and
66
+ * verifies the returned ID token for `client_id`. `Auth.Google.Token` accepts a Google ID token, as `token` or as
67
+ * the `id_token` of `tokens` (v3 body), whose audience is `client_id` or one of `audiences` (never an access
68
+ * token). Credentials are stored encrypted on the ident and emitted with `GoogleAuth.Tokens` after the login.
69
+ * @WebdaModda GoogleAuthentication
70
+ */
71
+ export declare class GoogleAuthentication<T extends GoogleParameters = GoogleParameters> extends OAuthProvider<T, GoogleAuthEvents> {
72
+ static Parameters: typeof GoogleParameters;
73
+ readonly providerName = "google";
74
+ /** Client verifying ID tokens: one per service so the Google certificates cache is reused */
75
+ protected verifier: OAuth2Client;
76
+ /** @override */
77
+ init(): Promise<this>;
80
78
  /**
81
- * We manage Google Auth Token
82
- * @returns true
79
+ * @param redirectUri - callback url
80
+ * @returns a Google OAuth client for the authorization url and the code exchange
83
81
  */
84
- hasToken(): boolean;
82
+ protected getClient(redirectUri?: string): OAuth2Client;
85
83
  /**
86
- * Generate the Google authorization url
87
- * @param redirect_uri - the url Google will redirect to
88
- * @param state - the random state to verify on callback
89
- * @param _ctx - the request context
90
- * @returns the authorization url
84
+ * @param request - authorization request
85
+ * @returns the Google authorization url
91
86
  */
92
- generateAuthUrl(redirect_uri: string, state: string, _ctx: WebContext): string;
87
+ getAuthorizationUrl(request: OAuthAuthorizationRequest): string;
93
88
  /**
94
- * Return a google oauth client
95
- * @param redirect_uri - the redirect url to use
96
- * @returns a new OAuth2 client
89
+ * Exchange the code with the PKCE verifier, verify the returned ID token for `client_id` and its nonce
90
+ * @param request - code exchange
91
+ * @returns the identity, with the credentials of the exchange
97
92
  */
98
- getOAuthClient(redirect_uri?: string): OAuth2Client;
93
+ handleCallback(request: OAuthCallbackRequest): Promise<ResolvedIdentity>;
99
94
  /**
100
- * @inheritdoc
101
- * @param ctx - the request context
102
- * @returns the identity and profile
95
+ * Verify a Google ID token sent by a client, as `token` or `tokens.id_token`
96
+ * @param request - token request
97
+ * @returns the identity, with the credentials sent in `tokens`
103
98
  */
104
- handleCallback(ctx: WebContext): Promise<{
105
- identId: any;
106
- profile: any;
107
- }>;
99
+ handleToken(request: OAuthTokenRequest): Promise<ResolvedIdentity>;
108
100
  /**
109
- * Retrieve the user profile based on the token
110
- * @param token - the Google id token
111
- * @returns the token payload
101
+ * Emit `GoogleAuth.Tokens` once the login succeeded
102
+ * @param identity - the identity
103
+ * @param _result - the result
104
+ * @param source - browser callback or token operation
105
+ * @param request - the token operation request
112
106
  */
113
- getUserInfo(token: string): Promise<import("google-auth-library").TokenPayload>;
107
+ protected onAuthenticated(identity: ResolvedIdentity, _result: AuthResult, source: "callback" | "token", request?: OAuthTokenRequest): Promise<void>;
114
108
  /**
115
- * Verify a Google Auth Token
116
- * @param context - the request context
117
- * @returns the identity and profile
109
+ * Verify an ID token: signature, expiry, issuer (google-auth-library), audience and hosted domain
110
+ * @param idToken - ID token
111
+ * @param audiences - accepted audiences
112
+ * @returns the payload
113
+ * @throws TokenInvalid when the token does not verify
114
+ * @throws EmailDomainNotAllowed when `hostedDomain` is set and the token is not from that domain
118
115
  */
119
- handleToken(context: WebContext): Promise<{
120
- identId: string;
121
- profile: import("google-auth-library").TokenPayload;
122
- }>;
116
+ protected verifyIdToken(idToken: string, audiences: string[]): Promise<TokenPayload>;
123
117
  /**
124
- * Retrieve Google Client
125
- *
126
- * Redirecting to the webbrowser for the OAuth validation
127
- * Store the token in user store afterwards
128
- * @param token - existing credentials to reuse, if any
129
- * @param open - callback to open the authorization url in a browser
130
- * @param storeToken - callback to persist the retrieved credentials
131
- * @returns the authenticated OAuth2 client
118
+ * @param payload - verified ID token payload
119
+ * @param tokens - credentials to store
120
+ * @returns the identity
132
121
  */
133
- getLocalClient(token: Credentials, open: (url: string) => void, storeToken: (token: Credentials) => Promise<void>): Promise<OAuth2Client>;
122
+ protected toIdentity(payload: TokenPayload, tokens?: Credentials): ResolvedIdentity;
134
123
  }
135
- export { GoogleAuthentication };
124
+ export default GoogleAuthentication;
136
125
  //# sourceMappingURL=google-auth.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-auth.service.d.ts","sourceRoot":"","sources":["../src/google-auth.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,sBAAsB,EAEtB,aAAa,EACb,UAAU,EAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGhE,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB,CAAC,UAAU,CAAC;IACzE;;OAEG;IACH,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,sBAAsB;IAC1D;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAEnC,YAAY,CAAC,EAAE,GAAG,CAAC;IACnB,SAAS,CAAC,EAAE;QAEV,WAAW,EAAE,OAAO,CAAC;QAErB,SAAS,EAAE,MAAM,EAAE,CAAC;QAEpB,QAAQ,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAC;KACrC,CAAC;IAEF;;;;OAIG;IACH,IAAI,CAAC,MAAM,GAAE,GAAQ,GAAG,IAAI,CAI3B;CACF;AAED,KAAK,gBAAgB,GAAG,WAAW,GAAG;IACpC,mBAAmB,EAAE,qBAAqB,CAAC;CAC5C,CAAC;AACF;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,oBAAoB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,CACrF,SAAQ,YAAY,CAAC,CAAC,EAAE,gBAAgB,CACxC,YAAW,aAAa,CAAC,UAAU,CAAC;IAEpC,SAAS,CAAC,OAAO,EAAE,YAAY,CAAC;IAEhC;;;OAGG;IACH,OAAO,WAEN;IAED;;;OAGG;IACH,kBAAkB,IAAI,MAAM,EAAE,CAE7B;IAED;;;OAGG;IACH,sBAAsB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,EAAE,CA2B9D;IAED;;;OAGG;IACH,aAAa,WAEZ;IAED;;;OAGG;IACH,QAAQ,YAEP;IAED;;;;;;OAMG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,UAUpE;IAED;;;;OAIG;IACH,cAAc,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,YAAY,CAElD;IAED;;;;OAIG;IACG,cAAc,CAAC,GAAG,EAAE,UAAU;;;OAwBnC;IAED;;;;OAIG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,uDAO9B;IAED;;;;OAIG;IACG,WAAW,CAAC,OAAO,EAAE,UAAU;;;OAUpC;IAED;;;;;;;;;OASG;IACG,cAAc,CAClB,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC3B,UAAU,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAChD,OAAO,CAAC,YAAY,CAAC,CAyDvB;CACF;AAED,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"google-auth.service.d.ts","sourceRoot":"","sources":["../src/google-auth.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,gBAAgB,EAAE,KAAK,gBAAgB,EAA0B,MAAM,aAAa,CAAC;AACpH,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,aAAa,EACb,uBAAuB,EACvB,KAAK,iBAAiB,EAGvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAuB,KAAK,WAAW,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE7G,gEAAgE;AAChE,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D;;;;OAIG;IACH,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,qCAAqC;AACrC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,mBAAmB,EAAE,qBAAqB,CAAC;CAC5C,CAAC;AAEF;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,uBAAuB;IAC3D;;OAEG;IACK,SAAS,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACK,aAAa,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACK,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACnC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAEnC;;;OAGG;IACH,IAAI,CAAC,MAAM,GAAE,GAAQ,GAAG,IAAI,CAM3B;CACF;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAoB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,CAAE,SAAQ,aAAa,CACpG,CAAC,EACD,gBAAgB,CACjB;IACC,MAAM,CAAC,UAAU,0BAAoB;IAErC,QAAQ,CAAC,YAAY,YAAY;IAEjC,6FAA6F;IAC7F,SAAS,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEjC,gBAAgB;IACV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAI1B;IAED;;;OAGG;IACH,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,CAMtD;IAED;;;OAGG;IACH,mBAAmB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAc9D;IAED;;;;OAIG;IACG,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAoB7E;IAED;;;;OAIG;IACG,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAcvE;IAED;;;;;;OAMG;IACH,UAAgB,eAAe,CAC7B,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,UAAU,GAAG,OAAO,EAC5B,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;IAED;;;;;;;OAOG;IACH,UAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CA2BzF;IAED;;;;OAIG;IACH,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,gBAAgB,CAUlF;CACF;eAcc,oBAAoB"}
@@ -1,241 +1,197 @@
1
- import { OAuthService, OAuthServiceParameters, WebdaError } from "@webda/core";
2
- import { OAuth2Client } from "google-auth-library";
3
- import * as http from "node:http";
1
+ import { timingSafeEqual } from "node:crypto";
2
+ import { useContext, WebdaError } from "@webda/core";
3
+ import { EmailDomainNotAllowed, OAuthProvider, OAuthProviderParameters, safeErrorReason, TokenInvalid } from "@webda/auth";
4
+ import { CodeChallengeMethod, OAuth2Client } from "google-auth-library";
4
5
  /**
5
- * Credentials to manage Google Auth
6
- * https://developers.google.com/identity/protocols/oauth2
6
+ * Google login parameters
7
+ * https://developers.google.com/identity/protocols/oauth2/openid-connect
7
8
  */
8
- export class GoogleParameters extends OAuthServiceParameters {
9
+ export class GoogleParameters extends OAuthProviderParameters {
9
10
  /**
10
- * Load parameters with Google defaults
11
- * @param params - the service parameters
11
+ * @param params - raw parameters
12
12
  * @returns this
13
13
  */
14
14
  load(params = {}) {
15
15
  super.load(params);
16
16
  this.access_type ?? (this.access_type = "online");
17
+ this.scope ?? (this.scope = ["openid", "email", "profile"]);
18
+ this.audiences ?? (this.audiences = []);
17
19
  return this;
18
20
  }
19
21
  }
20
22
  /**
21
- * Manage Google Authentication
23
+ * Sign in with Google (OpenID Connect)
22
24
  *
23
- * @WebdaModda
25
+ * The browser flow (`GET /auth/google`, `GET /auth/google/callback`) uses PKCE and a nonce, exchanges the code and
26
+ * verifies the returned ID token for `client_id`. `Auth.Google.Token` accepts a Google ID token, as `token` or as
27
+ * the `id_token` of `tokens` (v3 body), whose audience is `client_id` or one of `audiences` (never an access
28
+ * token). Credentials are stored encrypted on the ident and emitted with `GoogleAuth.Tokens` after the login.
29
+ * @WebdaModda GoogleAuthentication
24
30
  */
25
- export default class GoogleAuthentication extends OAuthService {
26
- /**
27
- * Return provider name
28
- * @returns the provider name
29
- */
30
- getName() {
31
- return "google";
31
+ export class GoogleAuthentication extends OAuthProvider {
32
+ constructor() {
33
+ super(...arguments);
34
+ this.providerName = "google";
32
35
  }
33
- /**
34
- * Allow every accounts.google.
35
- * @returns the referer patterns allowed to call back
36
- */
37
- getCallbackReferer() {
38
- return [/accounts\.google\.[a-z]+$/];
36
+ /** @override */
37
+ async init() {
38
+ await super.init();
39
+ this.verifier = new OAuth2Client({ clientId: this.parameters.client_id });
40
+ return this;
39
41
  }
40
42
  /**
41
- * Get OAuth callback query parameters
42
- * @returns the callback query parameters
43
+ * @param redirectUri - callback url
44
+ * @returns a Google OAuth client for the authorization url and the code exchange
43
45
  */
44
- getCallbackQueryParams() {
45
- return [
46
- {
47
- name: "code",
48
- required: true
49
- },
50
- {
51
- name: "scope",
52
- required: true
53
- },
54
- {
55
- name: "state",
56
- required: true
57
- },
58
- {
59
- name: "authuser",
60
- required: false
61
- },
62
- {
63
- name: "hd",
64
- required: false
65
- },
66
- {
67
- name: "prompt",
68
- required: false
69
- }
70
- ];
46
+ getClient(redirectUri) {
47
+ return new OAuth2Client({
48
+ clientId: this.parameters.client_id,
49
+ clientSecret: this.parameters.client_secret,
50
+ redirectUri
51
+ });
71
52
  }
72
53
  /**
73
- * Expose on /google by default
74
- * @returns the default url
54
+ * @param request - authorization request
55
+ * @returns the Google authorization url
75
56
  */
76
- getDefaultUrl() {
77
- return "/google";
57
+ getAuthorizationUrl(request) {
58
+ const { auth_options, access_type, hostedDomain } = this.parameters;
59
+ return this.getClient(request.redirectUri).generateAuthUrl({
60
+ ...(auth_options ?? {}),
61
+ access_type,
62
+ scope: request.scope,
63
+ state: request.state,
64
+ redirect_uri: request.redirectUri,
65
+ response_type: "code",
66
+ code_challenge_method: CodeChallengeMethod.S256,
67
+ code_challenge: request.codeChallenge,
68
+ nonce: request.nonce,
69
+ ...(hostedDomain ? { hd: hostedDomain } : {})
70
+ });
78
71
  }
79
72
  /**
80
- * We manage Google Auth Token
81
- * @returns true
73
+ * Exchange the code with the PKCE verifier, verify the returned ID token for `client_id` and its nonce
74
+ * @param request - code exchange
75
+ * @returns the identity, with the credentials of the exchange
82
76
  */
83
- hasToken() {
84
- return true;
77
+ async handleCallback(request) {
78
+ let tokens;
79
+ try {
80
+ ({ tokens } = await this.getClient(request.redirectUri).getToken({
81
+ code: request.code,
82
+ codeVerifier: request.codeVerifier,
83
+ redirect_uri: request.redirectUri
84
+ }));
85
+ }
86
+ catch (err) {
87
+ this.log("WARN", "Google code exchange failed:", safeErrorReason(err));
88
+ throw new TokenInvalid("Code exchange failed");
89
+ }
90
+ if (!tokens?.id_token) {
91
+ throw new TokenInvalid("Google returned no ID token: the 'openid' scope is required");
92
+ }
93
+ const payload = await this.verifyIdToken(tokens.id_token, [this.parameters.client_id]);
94
+ if (typeof payload.nonce !== "string" || !sameSecret(payload.nonce, request.nonce)) {
95
+ throw new TokenInvalid("ID token nonce mismatch");
96
+ }
97
+ return this.toIdentity(payload, tokens);
85
98
  }
86
99
  /**
87
- * Generate the Google authorization url
88
- * @param redirect_uri - the url Google will redirect to
89
- * @param state - the random state to verify on callback
90
- * @param _ctx - the request context
91
- * @returns the authorization url
100
+ * Verify a Google ID token sent by a client, as `token` or `tokens.id_token`
101
+ * @param request - token request
102
+ * @returns the identity, with the credentials sent in `tokens`
92
103
  */
93
- generateAuthUrl(redirect_uri, state, _ctx) {
94
- const oauthClient = this.getOAuthClient(redirect_uri);
95
- return oauthClient.generateAuthUrl({
96
- access_type: this.parameters.access_type,
97
- scope: this.parameters.scope,
98
- redirect_uri,
99
- response_type: "code",
100
- state,
101
- ...this.parameters.auth_options
102
- });
104
+ async handleToken(request) {
105
+ const fromTokens = request.tokens?.id_token;
106
+ if (request.token && fromTokens !== undefined && fromTokens !== request.token) {
107
+ throw new WebdaError.BadRequest("token and tokens.id_token differ");
108
+ }
109
+ const idToken = request.token ?? fromTokens;
110
+ if (typeof idToken !== "string" || !idToken) {
111
+ throw new TokenInvalid("A Google ID token is required");
112
+ }
113
+ const payload = await this.verifyIdToken(idToken, [
114
+ this.parameters.client_id,
115
+ ...(this.parameters.audiences ?? [])
116
+ ]);
117
+ return this.toIdentity(payload, request.tokens);
103
118
  }
104
119
  /**
105
- * Return a google oauth client
106
- * @param redirect_uri - the redirect url to use
107
- * @returns a new OAuth2 client
120
+ * Emit `GoogleAuth.Tokens` once the login succeeded
121
+ * @param identity - the identity
122
+ * @param _result - the result
123
+ * @param source - browser callback or token operation
124
+ * @param request - the token operation request
108
125
  */
109
- getOAuthClient(redirect_uri) {
110
- return new OAuth2Client(this.parameters.client_id, this.parameters.client_secret, redirect_uri);
126
+ async onAuthenticated(identity, _result, source, request) {
127
+ const tokens = source === "token" ? (request?.tokens ?? { id_token: request?.token }) : identity.tokens;
128
+ await this.emit("GoogleAuth.Tokens", { tokens, context: useContext() });
111
129
  }
112
130
  /**
113
- * @inheritdoc
114
- * @param ctx - the request context
115
- * @returns the identity and profile
131
+ * Verify an ID token: signature, expiry, issuer (google-auth-library), audience and hosted domain
132
+ * @param idToken - ID token
133
+ * @param audiences - accepted audiences
134
+ * @returns the payload
135
+ * @throws TokenInvalid when the token does not verify
136
+ * @throws EmailDomainNotAllowed when `hostedDomain` is set and the token is not from that domain
116
137
  */
117
- async handleCallback(ctx) {
118
- // Verify state are equal
119
- if (ctx.getParameters().state !== ctx.getSession().oauth?.state) {
120
- this.log("WARN", `Bad State ${ctx.getParameters().state} !== ${ctx.getSession().oauth?.state}`);
121
- throw new WebdaError.Forbidden("Bad State");
138
+ async verifyIdToken(idToken, audiences) {
139
+ const audience = audiences.filter(a => typeof a === "string" && a);
140
+ // Without audience the library would skip the check: never verify without one
141
+ if (!audience.length) {
142
+ throw new TokenInvalid("No audience configured");
122
143
  }
123
- const code = ctx.getParameters().code;
124
- const redirect_uri = ctx.getHttpContext().getAbsoluteUrl(`${this.parameters.url}/callback`);
125
- const oauthClient = this.getOAuthClient(redirect_uri);
126
- let profile, identId;
127
- // Now that we have the code, use that to acquire tokens.
144
+ this.verifier ?? (this.verifier = new OAuth2Client({ clientId: this.parameters.client_id }));
145
+ let payload;
128
146
  try {
129
- const r = await oauthClient.getToken(code);
130
- await this.emit("GoogleAuth.Tokens", { tokens: r.tokens, context: ctx });
131
- profile = await this.getUserInfo(r.tokens.id_token);
132
- identId = profile.sub;
147
+ const ticket = await this.verifier.verifyIdToken({
148
+ idToken,
149
+ audience: audience.length === 1 ? audience[0] : audience
150
+ });
151
+ payload = ticket.getPayload();
133
152
  }
134
153
  catch (err) {
135
- this.log("ERROR", err);
136
- throw new WebdaError.Forbidden("OAuth Error");
154
+ // The library messages contain the token or its payload: only the error class is logged
155
+ this.log("WARN", "Google ID token verification failed:", safeErrorReason(err));
156
+ throw new TokenInvalid();
137
157
  }
138
- return {
139
- identId,
140
- profile
141
- };
142
- }
143
- /**
144
- * Retrieve the user profile based on the token
145
- * @param token - the Google id token
146
- * @returns the token payload
147
- */
148
- async getUserInfo(token) {
149
- const oauthClient = this.getOAuthClient();
150
- const ticket = await oauthClient.verifyIdToken({
151
- idToken: token,
152
- audience: this.parameters.client_id
153
- });
154
- return ticket.getPayload();
158
+ if (!payload?.sub) {
159
+ throw new TokenInvalid("ID token has no subject");
160
+ }
161
+ const hostedDomain = this.parameters.hostedDomain?.trim().toLowerCase();
162
+ if (hostedDomain && payload.hd?.toLowerCase() !== hostedDomain) {
163
+ throw new EmailDomainNotAllowed("Google account is not from the hosted domain");
164
+ }
165
+ return payload;
155
166
  }
156
167
  /**
157
- * Verify a Google Auth Token
158
- * @param context - the request context
159
- * @returns the identity and profile
168
+ * @param payload - verified ID token payload
169
+ * @param tokens - credentials to store
170
+ * @returns the identity
160
171
  */
161
- async handleToken(context) {
162
- const tokens = (await context.getRequestBody()).tokens;
163
- if (!tokens) {
164
- throw new WebdaError.BadRequest("No tokens provided");
165
- }
166
- const profile = await this.getUserInfo(tokens.id_token);
172
+ toIdentity(payload, tokens) {
167
173
  return {
168
- identId: profile.sub,
169
- profile
174
+ provider: this.providerName,
175
+ providerUid: payload.sub,
176
+ email: payload.email,
177
+ emailVerified: payload.email_verified === true,
178
+ profile: { name: payload.name, picture: payload.picture, locale: payload.locale, hd: payload.hd },
179
+ tokens,
180
+ amr: ["oauth"]
170
181
  };
171
182
  }
172
- /**
173
- * Retrieve Google Client
174
- *
175
- * Redirecting to the webbrowser for the OAuth validation
176
- * Store the token in user store afterwards
177
- * @param token - existing credentials to reuse, if any
178
- * @param open - callback to open the authorization url in a browser
179
- * @param storeToken - callback to persist the retrieved credentials
180
- * @returns the authenticated OAuth2 client
181
- */
182
- async getLocalClient(token, open, storeToken) {
183
- if (this._client) {
184
- return this._client;
185
- }
186
- const oAuth2Client = this.getOAuthClient();
187
- if (token) {
188
- oAuth2Client.setCredentials(token);
189
- this._client = oAuth2Client;
190
- return oAuth2Client;
191
- }
192
- // Generate the url that will be used for the consent dialog.
193
- const authorizeUrl = oAuth2Client.generateAuthUrl({
194
- access_type: "offline",
195
- scope: this.parameters.scope,
196
- redirect_uri: "http://localhost:3000/oauth2callback"
197
- });
198
- // Open an http server to accept the oauth callback. In this simple example, the
199
- // only request to our webserver is to /oauth2callback?code=<code>
200
- return new Promise((resolve, reject) => {
201
- const server = http
202
- .createServer(async (req, res) => {
203
- if (req.url.indexOf("/oauth2callback") > -1) {
204
- try {
205
- // acquire the code from the querystring, and close the web server.
206
- const code = new URL(req.url, `http://localhost:3000`).searchParams.get("code");
207
- if (code) {
208
- res.end("Authentication successful! Please return to the console.");
209
- }
210
- else {
211
- res.end("Authentication unsuccessful! Please return to the console.");
212
- return reject("Failed");
213
- }
214
- // Now that we have the code, use that to acquire tokens.
215
- const r = await oAuth2Client.getToken(code);
216
- // Make sure to set the credentials on the OAuth2 client.
217
- storeToken(r.tokens);
218
- oAuth2Client.setCredentials(r.tokens);
219
- this._client = oAuth2Client;
220
- this.log("INFO", "Google Authentication finished.");
221
- return resolve(this._client);
222
- }
223
- catch (err) {
224
- this.log("ERROR", err);
225
- reject(err);
226
- }
227
- finally {
228
- server.close();
229
- }
230
- }
231
- })
232
- .listen(3000, () => {
233
- // open the browser to the authorize url to start the workflow
234
- this.log("INFO", "Launching your browser for Google API Permission");
235
- open(authorizeUrl);
236
- });
237
- });
238
- }
239
183
  }
240
- export { GoogleAuthentication };
184
+ GoogleAuthentication.Parameters = GoogleParameters;
185
+ /**
186
+ * Constant-time comparison
187
+ * @param a - received value
188
+ * @param b - expected value
189
+ * @returns true when equal
190
+ */
191
+ function sameSecret(a, b) {
192
+ const left = Buffer.from(a);
193
+ const right = Buffer.from(b);
194
+ return left.length === right.length && timingSafeEqual(left, right);
195
+ }
196
+ export default GoogleAuthentication;
241
197
  //# sourceMappingURL=google-auth.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"google-auth.service.js","sourceRoot":"","sources":["../src/google-auth.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"google-auth.service.js","sourceRoot":"","sources":["../src/google-auth.service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webda/google-auth",
3
- "version": "4.0.0-beta.3",
3
+ "version": "4.0.0-beta.4",
4
4
  "description": "Webda Google Authentication",
5
5
  "main": "lib/index.js",
6
6
  "repository": {
@@ -24,7 +24,8 @@
24
24
  "homepage": "https://github.com/loopingz/webda.io#readme",
25
25
  "dependencies": {
26
26
  "google-auth-library": "^10.6.2",
27
- "@webda/core": "4.0.0-beta.3"
27
+ "@webda/auth": "4.0.0-beta.4",
28
+ "@webda/core": "4.0.0-beta.4"
28
29
  },
29
30
  "publishConfig": {
30
31
  "access": "public"
@@ -38,8 +39,10 @@
38
39
  "typescript": "7.1.0-dev.20260929.1",
39
40
  "vite": "^6.0.0",
40
41
  "vitest": "^4.1.2",
41
- "@webda/compiler": "^4.0.0-beta.3",
42
- "@webda/test": "4.0.0-beta.3"
42
+ "@webda/compiler": "^4.0.0-beta.4",
43
+ "@webda/content-mapper": "^4.0.0-beta.4",
44
+ "@webda/test": "4.0.0-beta.3",
45
+ "@webda/workout": "4.0.0-beta.3"
43
46
  },
44
47
  "type": "module",
45
48
  "engines": {
@@ -47,7 +50,8 @@
47
50
  },
48
51
  "nx": {
49
52
  "implicitDependencies": [
50
- "@webda/core"
53
+ "@webda/core",
54
+ "@webda/auth"
51
55
  ]
52
56
  },
53
57
  "scripts": {
package/webda.module.json CHANGED
@@ -4,112 +4,125 @@
4
4
  "deployers": {},
5
5
  "moddas": {
6
6
  "Webda/GoogleAuthentication": {
7
- "Import": "lib/google-auth.service:default",
7
+ "Import": "lib/google-auth.service:GoogleAuthentication",
8
8
  "Schema": {
9
9
  "$schema": "http://json-schema.org/draft-07/schema#",
10
10
  "additionalProperties": false,
11
11
  "definitions": {
12
- "redirects": {
12
+ "OAuthRedirects": {
13
13
  "additionalProperties": false,
14
+ "description": "Browser redirects of the OAuth callback",
14
15
  "properties": {
15
- "defaults": {
16
- "$ref": "#/definitions/redirects%24defaults"
17
- },
18
- "use_referer": {
19
- "default": false,
20
- "type": "boolean"
16
+ "failure": {
17
+ "description": "Where a failed login or callback lands, with `?reason=<CODE>` (required)",
18
+ "type": "string"
21
19
  },
22
- "whitelist": {
23
- "items": {
24
- "type": "string"
25
- },
26
- "type": "array"
20
+ "success": {
21
+ "default": "/",
22
+ "description": "Where a successful login lands when the login did not carry an allowed `redirect` parameter",
23
+ "type": "string"
27
24
  }
28
25
  },
29
- "required": [
30
- "defaults",
31
- "whitelist"
32
- ],
33
26
  "type": "object"
34
27
  },
35
- "redirects$defaults": {
36
- "additionalProperties": {
37
- "type": "string"
38
- },
28
+ "Record<string, any>": {
29
+ "additionalProperties": {},
30
+ "description": "Construct a type with a set of properties K of type T",
39
31
  "type": "object"
40
32
  }
41
33
  },
42
- "description": "Credentials to manage Google Auth\nhttps://developers.google.com/identity/protocols/oauth2",
34
+ "description": "Google login parameters\nhttps://developers.google.com/identity/protocols/oauth2/openid-connect",
43
35
  "properties": {
44
36
  "access_type": {
45
- "description": "Type of access for Google token\n\nonline by default",
37
+ "default": "online",
38
+ "description": "Type of access: \"offline\" also returns a refresh token (stored encrypted in the ident tokens)",
46
39
  "enum": [
47
40
  "online",
48
41
  "offline"
49
42
  ],
50
43
  "type": "string"
51
44
  },
52
- "auth_options": {},
53
- "authenticationService": {
54
- "default": "Authentication",
55
- "description": "Name of the authentication service to use if exist",
56
- "type": "string"
45
+ "allowedEmailDomains": {
46
+ "description": "Only these email domains may use this provider (see ProviderEmailPolicy)",
47
+ "items": {
48
+ "type": "string"
49
+ },
50
+ "type": "array"
51
+ },
52
+ "audiences": {
53
+ "default": [],
54
+ "description": "Other client ids whose ID tokens `Auth.Google.Token` accepts (for example Android/iOS client ids)",
55
+ "items": {
56
+ "type": "string"
57
+ },
58
+ "type": "array"
59
+ },
60
+ "auth_options": {
61
+ "$ref": "#/definitions/Record%3Cstring%2C%20any%3E",
62
+ "description": "Additional authorization url parameters (for example `prompt`, `login_hint`); cannot override `state`,\n`redirect_uri`, `scope`, `access_type`, `response_type`, `code_challenge*`, `nonce` nor `hd`\nSee https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters"
57
63
  },
58
64
  "authorized_uris": {
59
65
  "default": [],
60
- "description": "List of URIs authorized for redirect post authorization",
66
+ "description": "Allowed post-login targets for the `redirect` query parameter of the login route: absolute http(s) urls, a\ntarget matches when it has the same origin and its path is the listed path or below it",
61
67
  "items": {
62
68
  "type": "string"
63
69
  },
64
70
  "type": "array"
65
71
  },
66
72
  "client_id": {
67
- "description": "Google Auth Client id",
73
+ "description": "Google OAuth client id (web application)",
68
74
  "type": "string"
69
75
  },
70
76
  "client_secret": {
71
- "description": "Google Auth Client secret",
77
+ "description": "Google OAuth client secret",
72
78
  "type": "string"
73
79
  },
74
- "exposeScope": {
75
- "default": false,
76
- "description": "If set to true it will add a ${url}/scope\nSo client can anticipate the requested scope\n\nThis is useful when using the client api to generate\ntoken. This way the service can request the wanted scope",
77
- "type": "boolean"
78
- },
79
- "no_referer": {
80
- "default": false,
81
- "description": "Allow direct connection without a referer",
82
- "type": "boolean"
83
- },
84
- "project_id": {
85
- "description": "Google Project ID",
80
+ "hostedDomain": {
81
+ "description": "Only accept Google Workspace accounts of this domain (the `hd` claim of the ID token); also sent as a hint to\nthe account chooser",
86
82
  "type": "string"
87
83
  },
88
84
  "redirect_uri": {
89
- "default": "${url}/callback",
90
- "description": "Default redirect_uri",
85
+ "default": "\"<absolute url of the request>/callback\"; set it explicitly behind a proxy",
86
+ "description": "Callback url registered at the provider",
91
87
  "type": "string"
92
88
  },
93
89
  "redirects": {
94
- "$ref": "#/definitions/redirects"
90
+ "$ref": "#/definitions/OAuthRedirects",
91
+ "description": "Browser redirects of the callback"
95
92
  },
96
93
  "scope": {
97
- "defaut": [
98
- "email"
94
+ "default": [
95
+ "openid",
96
+ "email",
97
+ "profile"
99
98
  ],
100
- "description": "Scope to request on OAuth flow",
99
+ "description": "Scopes requested from Google",
101
100
  "items": {
102
101
  "type": "string"
103
102
  },
104
103
  "type": "array"
105
104
  },
105
+ "trustEmailVerification": {
106
+ "anyOf": [
107
+ {
108
+ "items": {
109
+ "type": "string"
110
+ },
111
+ "type": "array"
112
+ },
113
+ {
114
+ "type": "boolean"
115
+ }
116
+ ],
117
+ "description": "Whether the verification of the email is believed (see ProviderEmailPolicy)"
118
+ },
106
119
  "type": {
107
120
  "description": "Type of the service",
108
121
  "type": "string"
109
122
  },
110
123
  "url": {
111
- "SchemaOptional": true,
112
- "description": "URL to use for expose\n\nThe default value varying based on implementation\nIt should by default be the provider name in lowercase",
124
+ "default": "/auth/<providerName>",
125
+ "description": "Route prefix of the login (`<url>`) and callback (`<url>/callback`) routes",
113
126
  "type": "string"
114
127
  },
115
128
  "openapi": {
@@ -120,16 +133,12 @@
120
133
  "required": [
121
134
  "client_id",
122
135
  "client_secret",
123
- "scope",
124
136
  "type"
125
137
  ],
126
138
  "type": "object",
127
139
  "title": "GoogleAuthentication"
128
140
  },
129
- "Configuration": "lib/google-auth.service:GoogleParameters",
130
- "capabilities": [
131
- "request-filter"
132
- ]
141
+ "Configuration": "lib/google-auth.service:GoogleParameters"
133
142
  }
134
143
  },
135
144
  "models": {},
@@ -175,6 +184,31 @@
175
184
  ],
176
185
  "type": "object",
177
186
  "title": "BinaryFile"
187
+ },
188
+ "Webda/OAuthTokenRequest": {
189
+ "$schema": "http://json-schema.org/draft-07/schema#",
190
+ "WebdaSchema": true,
191
+ "additionalProperties": false,
192
+ "definitions": {
193
+ "OAuthTokens": {
194
+ "additionalProperties": {},
195
+ "description": "Credentials as returned by an OAuth token endpoint (google-auth-library `Credentials` shape): `id_token`,\n`access_token`, `refresh_token`, `expiry_date`, `token_type`, `scope`... Values are not typed by the schema\n(providers send nulls); providers check what they use.",
196
+ "type": "object"
197
+ }
198
+ },
199
+ "description": "Input of the `Auth.<Provider>.Token` operations: `token`, or the provider credentials `tokens`",
200
+ "properties": {
201
+ "token": {
202
+ "description": "Token issued by the provider to the client (an ID token for OpenID Connect providers)",
203
+ "type": "string"
204
+ },
205
+ "tokens": {
206
+ "$ref": "#/definitions/OAuthTokens",
207
+ "description": "Credentials obtained by the client from the provider (v3 body; its `id_token` is verified)"
208
+ }
209
+ },
210
+ "type": "object",
211
+ "title": "OAuthTokenRequest"
178
212
  }
179
213
  },
180
214
  "behaviors": {}