mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-10-05 02:39:33 +02:00
Allow auth plugins to redirect to external url (#7179)
* Allow auth plugins to redirect to external url Add a new optional field to `RegisterServerExternalAuthenticatedResult`, the object passed to the `userAuthenticated` callback used by auth plugins. The server code uses this to redirect to an external website if it is set. Left TODO: - This code has been tested manually but a test case is still missing. - Here or in the plugin, the redirect urls must be limited to values configurable by admins. * rename to URI for consistency * add test for the new parameter * address review comments - correct syntax for optional parameter - handle the case where `externalAuthToken` has query parameters included
This commit is contained in:
parent
8c9b4abe45
commit
fc986076c9
4 changed files with 57 additions and 5 deletions
|
@ -39,6 +39,24 @@ async function register ({
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
const result = registerExternalAuth({
|
||||
authName: 'external-auth-9',
|
||||
authDisplayName: () => 'External Auth 9',
|
||||
onAuthRequest: (req, res) => {
|
||||
result.userAuthenticated({
|
||||
req,
|
||||
res,
|
||||
username: 'cid',
|
||||
email: 'cid@example.com',
|
||||
displayName: 'Cid Marquez',
|
||||
externalRedirectUri: 'https://external.com/some/redirect/path'
|
||||
})
|
||||
},
|
||||
onLogout: (user, req) => {
|
||||
return 'https://example.com/redirectUrl'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function unregister () {
|
||||
|
|
|
@ -77,7 +77,7 @@ describe('Test external auth plugins', function () {
|
|||
const config = await server.config.getConfig()
|
||||
|
||||
const auths = config.plugin.registeredExternalAuths
|
||||
expect(auths).to.have.lengthOf(9)
|
||||
expect(auths).to.have.lengthOf(10)
|
||||
|
||||
const auth2 = auths.find((a) => a.authName === 'external-auth-2')
|
||||
expect(auth2).to.exist
|
||||
|
@ -319,7 +319,7 @@ describe('Test external auth plugins', function () {
|
|||
const config = await server.config.getConfig()
|
||||
|
||||
const auths = config.plugin.registeredExternalAuths
|
||||
expect(auths).to.have.lengthOf(8)
|
||||
expect(auths).to.have.lengthOf(9)
|
||||
|
||||
const auth1 = auths.find(a => a.authName === 'external-auth-2')
|
||||
expect(auth1).to.not.exist
|
||||
|
@ -400,7 +400,7 @@ describe('Test external auth plugins', function () {
|
|||
const config = await server.config.getConfig()
|
||||
|
||||
const auths = config.plugin.registeredExternalAuths
|
||||
expect(auths).to.have.lengthOf(7)
|
||||
expect(auths).to.have.lengthOf(8)
|
||||
|
||||
const auth2 = auths.find((a) => a.authName === 'external-auth-2')
|
||||
expect(auth2).to.not.exist
|
||||
|
@ -433,4 +433,29 @@ describe('Test external auth plugins', function () {
|
|||
const { redirectUrl } = await server.login.logout({ token: resLogin.access_token })
|
||||
expect(redirectUrl).to.equal('https://example.com/redirectUrl?access_token=' + resLogin.access_token)
|
||||
})
|
||||
|
||||
it('Should redirect to an external site after login if externalRedirectUri is set', async function () {
|
||||
|
||||
const res = await server.plugins.getExternalAuth({
|
||||
npmName: 'test-external-auth-three',
|
||||
npmVersion: '0.0.1',
|
||||
authName: 'external-auth-9',
|
||||
query: {
|
||||
username: 'cid'
|
||||
},
|
||||
expectedStatus: HttpStatusCode.FOUND_302
|
||||
})
|
||||
|
||||
const location = res.header.location
|
||||
expect(location.startsWith('https://external.com/some/redirect/path?')).to.be.true
|
||||
|
||||
const searchParams = decodeQueryString(location)
|
||||
|
||||
expect(searchParams.externalAuthToken).to.exist
|
||||
expect(searchParams.username).to.equal('cid')
|
||||
|
||||
externalAuthToken = searchParams.externalAuthToken as string
|
||||
|
||||
await server.login.loginUsingExternalToken({ username: 'cid', externalAuthToken, expectedStatus: HttpStatusCode.OK_200 })
|
||||
})
|
||||
})
|
||||
|
|
|
@ -45,7 +45,7 @@ async function onExternalUserAuthenticated (options: {
|
|||
return
|
||||
}
|
||||
|
||||
const { res } = authResult
|
||||
const { res, externalRedirectUri } = authResult
|
||||
|
||||
if (!isAuthResultValid(npmName, authName, authResult)) {
|
||||
res.redirect('/login?externalAuthError=true')
|
||||
|
@ -76,7 +76,14 @@ async function onExternalUserAuthenticated (options: {
|
|||
}
|
||||
}
|
||||
|
||||
if (externalRedirectUri) {
|
||||
const url = new URL(externalRedirectUri)
|
||||
url.searchParams.set('externalAuthToken', bypassToken)
|
||||
url.searchParams.set('username', user.username)
|
||||
res.redirect(url.href)
|
||||
} else {
|
||||
res.redirect(`/login?externalAuthToken=${bypassToken}&username=${user.username}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function getAuthNameFromRefreshGrant (refreshToken?: string) {
|
||||
|
|
|
@ -33,6 +33,8 @@ export interface RegisterServerAuthenticatedResult {
|
|||
export interface RegisterServerExternalAuthenticatedResult extends RegisterServerAuthenticatedResult {
|
||||
req: express.Request
|
||||
res: express.Response
|
||||
// Redirect the user to this external URI after the external auth has been verified.
|
||||
externalRedirectUri?: string
|
||||
}
|
||||
|
||||
interface RegisterServerAuthBase {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue