Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve GoogleProvider type and better support social auth for SPA #1277

Merged
merged 7 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions docs/blog/version-4.5-release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,36 @@ export class SubscriptionService {

```

## Social authentication for SPAs

If you wish to manually manage the redirection to the consent page on the client side (which is often necessary when developing an SPA), you can now do so with the `createHttpResponseWithConsentPageUrl` method. It returns an `HttpResponseOK` whose body contains the URL of the consent page.

```typescript
export class AuthController {
@dependency
google: GoogleProvider;

@Get('/signin/google')
getConsentPageURL() {
return this.google.createHttpResponseWithConsentPageUrl();
}

// ...

}

```

## Google social authentification

The typing of the `GoogleProvider` service has been improved. The `userInfo` property returned by `getUserInfo` is now typed with the values returned by the Google server.

```typescript
const { userInfo } = await this.googleProvider.getUserInfo(...);

// userInfo.email, userInfo.family_name, etc
```

## Logging improvements

In previous versions, the util function `displayServerURL` and configuration errors printed logs on several lines, which was not appropriate for logging software.
Expand Down
26 changes: 14 additions & 12 deletions docs/docs/authentication/social-auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class AuthController {
redirectToGoogle() {
// Your "Login In with Google" button should point to this route.
// The user will be redirected to Google auth page.
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/callback')
Expand All @@ -157,11 +157,13 @@ export class AuthController {

You can also override in the `redirect` method the scopes you want:
```typescript
return this.google.redirect({ scopes: [ 'email' ] });
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true, scopes: [ 'email' ] });
```

Additional parameters can passed to the `redirect` and `getUserInfo` methods depending on the provider.

> If you want to manage the redirection on the client side manually, don't specify the `isRedirection` option. In this case, the `createHttpResponseWithConsentPageUrl` method returns an `HttpResponseOK` whose body contains the URL of the consent page. The name of the body property is `consentPageUrl`.

## Techniques

### Usage with sessions
Expand Down Expand Up @@ -210,15 +212,15 @@ export class AuthController {

@Get('/signin/google')
redirectToGoogle() {
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/callback')
@UseSessions({
cookie: true,
})
async handleGoogleRedirection(ctx: Context<User>) {
const { userInfo } = await this.google.getUserInfo<{ email: string }>(ctx);
const { userInfo } = await this.google.getUserInfo(ctx);

if (!userInfo.email) {
throw new Error('Google should have returned an email address.');
Expand Down Expand Up @@ -285,12 +287,12 @@ export class AuthController {

@Get('/signin/google')
redirectToGoogle() {
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/callback')
async handleGoogleRedirection(ctx: Context) {
const { userInfo } = await this.google.getUserInfo<{ email: string }>(ctx);
const { userInfo } = await this.google.getUserInfo(ctx);

if (!userInfo.email) {
throw new Error('Google should have returned an email address.');
Expand Down Expand Up @@ -442,11 +444,11 @@ Visit the [Google API Console](https://console.developers.google.com/apis/creden

#### Redirection parameters

The `redirect` method of the `GoogleProvider` accepts additional parameters. These parameters and their description are listed [here](https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters) and are all optional.
The `createHttpResponseWithConsentPageUrl` method of the `GoogleProvider` accepts additional parameters. These parameters and their description are listed [here](https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters) and are all optional.

*Example*
```typescript
this.google.redirect({ /* ... */ }, {
this.google.createHttpResponseWithConsentPageUrl({ /* ... */ }, {
access_type: 'offline'
})
```
Expand All @@ -463,11 +465,11 @@ Visit [Facebook's developer website](https://developers.facebook.com/) to create

#### Redirection parameters

The `redirect` method of the `FacebookProvider` accepts an additional `auth_type` parameter which is optional.
The `createHttpResponseWithConsentPageUrl` method of the `FacebookProvider` accepts an additional `auth_type` parameter which is optional.

*Example*
```typescript
this.facebook.redirect({ /* ... */ }, {
this.facebook.createHttpResponseWithConsentPageUrl({ /* ... */ }, {
auth_type: 'rerequest'
});
```
Expand Down Expand Up @@ -505,11 +507,11 @@ Additional documentation on Github's redirect URLs can be found [here](https://d

#### Redirection parameters

The `redirect` method of the `GithubProvider` accepts additional parameters. These parameters and their description are listed below and are all optional.
The `createHttpResponseWithConsentPageUrl` method of the `GithubProvider` accepts additional parameters. These parameters and their description are listed below and are all optional.

*Example*
```typescript
this.github.redirect({ /* ... */ }, {
this.github.createHttpResponseWithConsentPageUrl({ /* ... */ }, {
allow_signup: false
})
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class SocialAuthController {

@Get('/google')
redirectToGoogle() {
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/google/callback')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Feature: Adding social auth controllers', () => {
redirectToGoogle() {
// Your "Login In with Google" button should point to this route.
// The user will be redirected to Google auth page.
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/callback')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ describe('Feature: Using social auth with JWT', () => {

@Get('/signin/google')
redirectToGoogle() {
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/callback')
async handleGoogleRedirection(ctx: Context) {
const { userInfo } = await this.google.getUserInfo<{ email: string }>(ctx);
const { userInfo } = await this.google.getUserInfo(ctx);

if (!userInfo.email) {
throw new Error('Google should have returned an email address.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ describe('Feature: Using social auth with sessions', () => {

@Get('/signin/google')
redirectToGoogle() {
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/callback')
@UseSessions({
cookie: true,
})
async handleGoogleRedirection(ctx: Context<User>) {
const { userInfo } = await this.google.getUserInfo<{ email: string }>(ctx);
const { userInfo } = await this.google.getUserInfo(ctx);

if (!userInfo.email) {
throw new Error('Google should have returned an email address.');
Expand Down
10 changes: 5 additions & 5 deletions packages/examples/src/app/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export class AuthController {

@Get('/signin/google')
redirectToGoogle() {
return this.google.redirect();
return this.google.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/google/cb')
Expand All @@ -43,7 +43,7 @@ export class AuthController {

@Get('/signin/facebook')
redirectToFacebook() {
return this.facebook.redirect();
return this.facebook.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/facebook/cb')
Expand All @@ -54,7 +54,7 @@ export class AuthController {

@Get('/signin/github')
redirectToGithub() {
return this.github.redirect();
return this.github.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/github/cb')
Expand All @@ -65,7 +65,7 @@ export class AuthController {

@Get('/signin/linkedin')
redirectToLinkedIn() {
return this.linkedin.redirect();
return this.linkedin.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/linkedin/cb')
Expand All @@ -76,7 +76,7 @@ export class AuthController {

@Get('/signin/twitter')
redirectToTwitter() {
return this.twitter.redirect();
return this.twitter.createHttpResponseWithConsentPageUrl({ isRedirection: true });
}

@Get('/signin/twitter/cb')
Expand Down
Loading
Loading