Merge branch 'artonge/PeerTube-feature/logoutUrlForAuthProviders' into 'develop'
Artonge/peer tube feature/logout url for auth providers See merge request framasoft/peertube/PeerTube!33
This commit is contained in:
commit
db7510d632
|
@ -167,9 +167,13 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular
|
|||
const authHeaderValue = this.getRequestHeaderValue()
|
||||
const headers = new HttpHeaders().set('Authorization', authHeaderValue)
|
||||
|
||||
this.http.post<void>(AuthService.BASE_REVOKE_TOKEN_URL, {}, { headers })
|
||||
this.http.post<{ redirectUrl?: string }>(AuthService.BASE_REVOKE_TOKEN_URL, {}, { headers })
|
||||
.subscribe(
|
||||
() => { /* nothing to do */ },
|
||||
res => {
|
||||
if (res.redirectUrl) {
|
||||
window.location.href = res.redirectUrl
|
||||
}
|
||||
},
|
||||
|
||||
err => console.error(err)
|
||||
)
|
||||
|
|
|
@ -52,7 +52,7 @@ async function handleTokenRevocation (req: express.Request, res: express.Respons
|
|||
const token = res.locals.oauth.token
|
||||
|
||||
res.locals.explicitLogout = true
|
||||
await revokeToken(token)
|
||||
const result = await revokeToken(token)
|
||||
|
||||
// FIXME: uncomment when https://github.com/oauthjs/node-oauth2-server/pull/289 is released
|
||||
// oAuthServer.revoke(req, res, err => {
|
||||
|
@ -68,7 +68,7 @@ async function handleTokenRevocation (req: express.Request, res: express.Respons
|
|||
// }
|
||||
// })
|
||||
|
||||
return res.json()
|
||||
return res.json(result)
|
||||
}
|
||||
|
||||
async function onExternalUserAuthenticated (options: {
|
||||
|
|
|
@ -141,13 +141,15 @@ async function getUser (usernameOrEmail?: string, password?: string) {
|
|||
return user
|
||||
}
|
||||
|
||||
async function revokeToken (tokenInfo: { refreshToken: string }) {
|
||||
async function revokeToken (tokenInfo: { refreshToken: string }): Promise<{ success: boolean, redirectUrl?: string }> {
|
||||
const res: express.Response = this.request.res
|
||||
const token = await OAuthTokenModel.getByRefreshTokenAndPopulateUser(tokenInfo.refreshToken)
|
||||
|
||||
if (token) {
|
||||
let redirectUrl: string
|
||||
|
||||
if (res.locals.explicitLogout === true && token.User.pluginAuth && token.authName) {
|
||||
PluginManager.Instance.onLogout(token.User.pluginAuth, token.authName, token.User)
|
||||
redirectUrl = await PluginManager.Instance.onLogout(token.User.pluginAuth, token.authName, token.User, this.request)
|
||||
}
|
||||
|
||||
clearCacheByToken(token.accessToken)
|
||||
|
@ -155,10 +157,10 @@ async function revokeToken (tokenInfo: { refreshToken: string }) {
|
|||
token.destroy()
|
||||
.catch(err => logger.error('Cannot destroy token when revoking token.', { err }))
|
||||
|
||||
return true
|
||||
return { success: true, redirectUrl }
|
||||
}
|
||||
|
||||
return false
|
||||
return { success: false }
|
||||
}
|
||||
|
||||
async function saveToken (token: TokenInfo, client: OAuthClientModel, user: UserModel) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import * as express from 'express'
|
||||
import { createReadStream, createWriteStream } from 'fs'
|
||||
import { outputFile, readJSON } from 'fs-extra'
|
||||
import { basename, join } from 'path'
|
||||
|
@ -166,18 +167,25 @@ export class PluginManager implements ServerHook {
|
|||
|
||||
// ###################### External events ######################
|
||||
|
||||
onLogout (npmName: string, authName: string, user: MUser) {
|
||||
async onLogout (npmName: string, authName: string, user: MUser, req: express.Request) {
|
||||
const auth = this.getAuth(npmName, authName)
|
||||
|
||||
if (auth?.onLogout) {
|
||||
logger.info('Running onLogout function from auth %s of plugin %s', authName, npmName)
|
||||
|
||||
try {
|
||||
auth.onLogout(user)
|
||||
// Force await, in case or onLogout returns a promise
|
||||
const result = await auth.onLogout(user, req)
|
||||
|
||||
return typeof result === 'string'
|
||||
? result
|
||||
: undefined
|
||||
} catch (err) {
|
||||
logger.warn('Cannot run onLogout function from auth %s of plugin %s.', authName, npmName, { err })
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
onSettingsChanged (name: string, settings: any) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
async function register ({
|
||||
registerExternalAuth,
|
||||
peertubeHelpers
|
||||
}) {
|
||||
{
|
||||
const result = registerExternalAuth({
|
||||
authName: 'external-auth-7',
|
||||
authDisplayName: () => 'External Auth 7',
|
||||
onAuthRequest: (req, res) => {
|
||||
result.userAuthenticated({
|
||||
req,
|
||||
res,
|
||||
username: 'cid',
|
||||
email: 'cid@example.com',
|
||||
displayName: 'Cid Marquez'
|
||||
})
|
||||
},
|
||||
onLogout: (user, req) => {
|
||||
return 'https://example.com/redirectUrl'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
const result = registerExternalAuth({
|
||||
authName: 'external-auth-8',
|
||||
authDisplayName: () => 'External Auth 8',
|
||||
onAuthRequest: (req, res) => {
|
||||
result.userAuthenticated({
|
||||
req,
|
||||
res,
|
||||
username: 'cid',
|
||||
email: 'cid@example.com',
|
||||
displayName: 'Cid Marquez'
|
||||
})
|
||||
},
|
||||
onLogout: (user, req) => {
|
||||
return 'https://example.com/redirectUrl?access_token=' + req.headers['authorization'].split(' ')[1]
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function unregister () {
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
register,
|
||||
unregister
|
||||
}
|
||||
|
||||
// ###########################################################################
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "peertube-plugin-test-external-auth-three",
|
||||
"version": "0.0.1",
|
||||
"description": "External auth three",
|
||||
"engine": {
|
||||
"peertube": ">=1.3.0"
|
||||
},
|
||||
"keywords": [
|
||||
"peertube",
|
||||
"plugin"
|
||||
],
|
||||
"homepage": "https://github.com/Chocobozzz/PeerTube",
|
||||
"author": "Chocobozzz",
|
||||
"bugs": "https://github.com/Chocobozzz/PeerTube/issues",
|
||||
"library": "./main.js",
|
||||
"staticDirs": {},
|
||||
"css": [],
|
||||
"clientScripts": [],
|
||||
"translations": {}
|
||||
}
|
|
@ -73,7 +73,7 @@ describe('Test external auth plugins', function () {
|
|||
server = await flushAndRunServer(1)
|
||||
await setAccessTokensToServers([ server ])
|
||||
|
||||
for (const suffix of [ 'one', 'two' ]) {
|
||||
for (const suffix of [ 'one', 'two', 'three' ]) {
|
||||
await installPlugin({
|
||||
url: server.url,
|
||||
accessToken: server.accessToken,
|
||||
|
@ -88,7 +88,7 @@ describe('Test external auth plugins', function () {
|
|||
const config: ServerConfig = res.body
|
||||
|
||||
const auths = config.plugin.registeredExternalAuths
|
||||
expect(auths).to.have.lengthOf(6)
|
||||
expect(auths).to.have.lengthOf(8)
|
||||
|
||||
const auth2 = auths.find((a) => a.authName === 'external-auth-2')
|
||||
expect(auth2).to.exist
|
||||
|
@ -301,7 +301,7 @@ describe('Test external auth plugins', function () {
|
|||
const config: ServerConfig = res.body
|
||||
|
||||
const auths = config.plugin.registeredExternalAuths
|
||||
expect(auths).to.have.lengthOf(5)
|
||||
expect(auths).to.have.lengthOf(7)
|
||||
|
||||
const auth1 = auths.find(a => a.authName === 'external-auth-2')
|
||||
expect(auth1).to.not.exist
|
||||
|
@ -371,7 +371,7 @@ describe('Test external auth plugins', function () {
|
|||
const config: ServerConfig = res.body
|
||||
|
||||
const auths = config.plugin.registeredExternalAuths
|
||||
expect(auths).to.have.lengthOf(4)
|
||||
expect(auths).to.have.lengthOf(6)
|
||||
|
||||
const auth2 = auths.find((a) => a.authName === 'external-auth-2')
|
||||
expect(auth2).to.not.exist
|
||||
|
@ -380,4 +380,30 @@ describe('Test external auth plugins', function () {
|
|||
after(async function () {
|
||||
await cleanupTests([ server ])
|
||||
})
|
||||
|
||||
it('Should forward the redirectUrl if the plugin returns one', async function () {
|
||||
const resLogin = await loginExternal({
|
||||
server,
|
||||
npmName: 'test-external-auth-three',
|
||||
authName: 'external-auth-7',
|
||||
username: 'cid'
|
||||
})
|
||||
|
||||
const resLogout = await logout(server.url, resLogin.access_token)
|
||||
|
||||
expect(resLogout.body.redirectUrl).to.equal('https://example.com/redirectUrl')
|
||||
})
|
||||
|
||||
it('Should call the plugin\'s onLogout method with the request', async function () {
|
||||
const resLogin = await loginExternal({
|
||||
server,
|
||||
npmName: 'test-external-auth-three',
|
||||
authName: 'external-auth-8',
|
||||
username: 'cid'
|
||||
})
|
||||
|
||||
const resLogout = await logout(server.url, resLogin.access_token)
|
||||
|
||||
expect(resLogout.body.redirectUrl).to.equal('https://example.com/redirectUrl?access_token=' + resLogin.access_token)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -21,7 +21,8 @@ interface RegisterServerAuthBase {
|
|||
authName: string
|
||||
|
||||
// Called by PeerTube when a user from your plugin logged out
|
||||
onLogout?(user: MUser): void
|
||||
// Returns a redirectUrl sent to the client or nothing
|
||||
onLogout?(user: MUser, req: express.Request): Promise<string>
|
||||
|
||||
// Your plugin can hook PeerTube access/refresh token validity
|
||||
// So you can control for your plugin the user session lifetime
|
||||
|
|
Loading…
Reference in New Issue