fix(@hono/oauth-providers): Added missing URL parameters prompt, login_hint, and access_type in the Google OAuth provider. (#697)
* fix: google provider attach custom parameters * fix format * Create rare-fishes-sort.mdpull/698/head
parent
2528a9fd63
commit
c3b67a6c3b
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@hono/oauth-providers": patch
|
||||
---
|
||||
|
||||
fix(@hono/oauth-providers): google provider attach custom parameters
|
|
@ -14,6 +14,7 @@ type GoogleAuthFlow = {
|
|||
state?: string
|
||||
login_hint?: string
|
||||
prompt?: 'none' | 'consent' | 'select_account'
|
||||
access_type?: 'offline' | 'online'
|
||||
}
|
||||
|
||||
export class AuthFlow {
|
||||
|
@ -28,6 +29,7 @@ export class AuthFlow {
|
|||
prompt: 'none' | 'consent' | 'select_account' | undefined
|
||||
user: Partial<GoogleUser> | undefined
|
||||
granted_scopes: string[] | undefined
|
||||
access_type: 'offline' | 'online' | undefined
|
||||
|
||||
constructor({
|
||||
client_id,
|
||||
|
@ -39,6 +41,7 @@ export class AuthFlow {
|
|||
state,
|
||||
code,
|
||||
token,
|
||||
access_type,
|
||||
}: GoogleAuthFlow) {
|
||||
this.client_id = client_id
|
||||
this.client_secret = client_secret
|
||||
|
@ -51,6 +54,7 @@ export class AuthFlow {
|
|||
this.token = token
|
||||
this.user = undefined
|
||||
this.granted_scopes = undefined
|
||||
this.access_type = access_type
|
||||
|
||||
if (
|
||||
this.client_id === undefined ||
|
||||
|
@ -71,6 +75,9 @@ export class AuthFlow {
|
|||
include_granted_scopes: true,
|
||||
scope: this.scope.join(' '),
|
||||
state: this.state,
|
||||
prompt: this.prompt,
|
||||
login_hint: this.login_hint,
|
||||
access_type: this.access_type,
|
||||
})
|
||||
return `https://accounts.google.com/o/oauth2/v2/auth?${parsedOptions}`
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { MiddlewareHandler } from 'hono'
|
||||
import { getCookie, setCookie } from 'hono/cookie'
|
||||
import { env } from 'hono/adapter'
|
||||
import { getCookie, setCookie } from 'hono/cookie'
|
||||
import { HTTPException } from 'hono/http-exception'
|
||||
|
||||
import { getRandomState } from '../../utils/getRandomState'
|
||||
|
@ -10,6 +10,7 @@ export function googleAuth(options: {
|
|||
scope: string[]
|
||||
login_hint?: string
|
||||
prompt?: 'none' | 'consent' | 'select_account'
|
||||
access_type?: 'online' | 'offline'
|
||||
client_id?: string
|
||||
client_secret?: string
|
||||
state?: string
|
||||
|
@ -24,6 +25,7 @@ export function googleAuth(options: {
|
|||
redirect_uri: options.redirect_uri || c.req.url.split('?')[0],
|
||||
login_hint: options.login_hint,
|
||||
prompt: options.prompt,
|
||||
access_type: options.access_type,
|
||||
scope: options.scope,
|
||||
state: newState,
|
||||
code: c.req.query('code'),
|
||||
|
|
|
@ -70,6 +70,18 @@ describe('OAuth Middleware', () => {
|
|||
redirect_uri: 'http://localhost:3000/google',
|
||||
})(c, next)
|
||||
})
|
||||
app.use('/google-custom-params', (c, next) => {
|
||||
return googleAuth({
|
||||
client_id,
|
||||
client_secret,
|
||||
scope: ['openid', 'email', 'profile'],
|
||||
redirect_uri: 'http://localhost:3000/google',
|
||||
login_hint: 'test-login-hint',
|
||||
prompt: 'select_account',
|
||||
state: 'test-state',
|
||||
access_type: 'offline',
|
||||
})(c, next)
|
||||
})
|
||||
app.get('/google', (c) => {
|
||||
const user = c.get('user-google')
|
||||
const token = c.get('token')
|
||||
|
@ -356,6 +368,21 @@ describe('OAuth Middleware', () => {
|
|||
expect(redirectUrl.searchParams.get('redirect_uri')).toBe('http://localhost:3000/google')
|
||||
})
|
||||
|
||||
it('Should attach custom parameters', async () => {
|
||||
const res = await app.request('/google-custom-params')
|
||||
expect(res).not.toBeNull()
|
||||
expect(res.status).toBe(302)
|
||||
|
||||
const redirectLocation = res.headers.get('location')!
|
||||
const redirectUrl = new URL(redirectLocation)
|
||||
expect(redirectUrl.searchParams.get('redirect_uri')).toBe('http://localhost:3000/google')
|
||||
expect(redirectUrl.searchParams.get('scope')).toBe('openid email profile')
|
||||
expect(redirectUrl.searchParams.get('login_hint')).toBe('test-login-hint')
|
||||
expect(redirectUrl.searchParams.get('prompt')).toBe('select_account')
|
||||
expect(redirectUrl.searchParams.get('state')).toBe('test-state')
|
||||
expect(redirectUrl.searchParams.get('access_type')).toBe('offline')
|
||||
})
|
||||
|
||||
it('Prevent CSRF attack', async () => {
|
||||
const res = await app.request(`/google?code=${dummyCode}&state=malware-state`)
|
||||
|
||||
|
|
Loading…
Reference in New Issue