Fix SAML signature
This commit is contained in:
parent
147538fa8e
commit
07fa3d9a2e
@ -1,3 +1,17 @@
|
|||||||
# SAML2 auth plugin for PeerTube
|
# SAML2 auth plugin for PeerTube
|
||||||
|
|
||||||
Add SAML2 support to login form in PeerTube.
|
Add SAML2 support to login form in PeerTube.
|
||||||
|
|
||||||
|
## Keycloak example
|
||||||
|
|
||||||
|
### Signature
|
||||||
|
|
||||||
|
If you want to sign get requests:
|
||||||
|
* Generate a certificate and private key: `openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem`
|
||||||
|
* Import `cert.pem` in keycloak SAML client
|
||||||
|
* Copy `cert.pem` and `key.pem` in PeerTube SAML plugin settings
|
||||||
|
* Check the *Sign get request* checkbox in PeerTube SAML plugin settings
|
||||||
|
|
||||||
|
### Provider certificate
|
||||||
|
|
||||||
|
You can find the public key on: `http://keycloak.example.com/auth/realms/{realm}/protocol/saml/descriptor`.
|
||||||
|
@ -29,14 +29,6 @@ async function register ({
|
|||||||
default: metadataUrl
|
default: metadataUrl
|
||||||
})
|
})
|
||||||
|
|
||||||
registerSetting({
|
|
||||||
name: 'sign-get-request',
|
|
||||||
label: 'Sign get request',
|
|
||||||
type: 'input-checkbox',
|
|
||||||
private: true,
|
|
||||||
default: false
|
|
||||||
})
|
|
||||||
|
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'auth-display-name',
|
name: 'auth-display-name',
|
||||||
label: 'Auth display name',
|
label: 'Auth display name',
|
||||||
@ -54,11 +46,33 @@ async function register ({
|
|||||||
|
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'provider-certificate',
|
name: 'provider-certificate',
|
||||||
label: 'Identity provider certificate',
|
label: 'Identity provider certificate (PEM format)',
|
||||||
type: 'input-textarea',
|
type: 'input-textarea',
|
||||||
private: true
|
private: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'service-certificate',
|
||||||
|
label: 'Service certificate (PEM format)',
|
||||||
|
type: 'input-textarea',
|
||||||
|
private: true
|
||||||
|
})
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'service-private-key',
|
||||||
|
label: 'Service private key (PEM format)',
|
||||||
|
type: 'input-textarea',
|
||||||
|
private: true
|
||||||
|
})
|
||||||
|
|
||||||
|
registerSetting({
|
||||||
|
name: 'sign-get-request',
|
||||||
|
label: 'Sign get request',
|
||||||
|
type: 'input-checkbox',
|
||||||
|
private: true,
|
||||||
|
default: false
|
||||||
|
})
|
||||||
|
|
||||||
registerSetting({
|
registerSetting({
|
||||||
name: 'username-property',
|
name: 'username-property',
|
||||||
label: 'Username property',
|
label: 'Username property',
|
||||||
@ -145,7 +159,9 @@ async function loadSettingsAndCreateProviders (
|
|||||||
'client-id',
|
'client-id',
|
||||||
'sign-get-request',
|
'sign-get-request',
|
||||||
'login-url',
|
'login-url',
|
||||||
'provider-certificate'
|
'provider-certificate',
|
||||||
|
'service-certificate',
|
||||||
|
'service-private-key'
|
||||||
])
|
])
|
||||||
|
|
||||||
if (!settings['login-url']) {
|
if (!settings['login-url']) {
|
||||||
@ -158,12 +174,12 @@ async function loadSettingsAndCreateProviders (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { publicKey: servicePublicKey, privateKey: servicePrivateKey } = await lazyLoadServiceCertificates(peertubeHelpers, storageManager)
|
logger.debug('Creating SAML service/identity instances.', { settings })
|
||||||
|
|
||||||
const serviceOptions = {
|
const serviceOptions = {
|
||||||
entity_id: settings['client-id'],
|
entity_id: settings['client-id'],
|
||||||
private_key: servicePrivateKey,
|
private_key: settings['service-private-key'],
|
||||||
certificate: servicePublicKey,
|
certificate: settings['service-certificate'],
|
||||||
assert_endpoint: store.assertUrl
|
assert_endpoint: store.assertUrl
|
||||||
}
|
}
|
||||||
store.serviceProvider = new saml2.ServiceProvider(serviceOptions)
|
store.serviceProvider = new saml2.ServiceProvider(serviceOptions)
|
||||||
@ -182,6 +198,7 @@ async function loadSettingsAndCreateProviders (
|
|||||||
authName: 'saml2',
|
authName: 'saml2',
|
||||||
authDisplayName: () => store.authDisplayName,
|
authDisplayName: () => store.authDisplayName,
|
||||||
onAuthRequest: async (req, res) => {
|
onAuthRequest: async (req, res) => {
|
||||||
|
try {
|
||||||
store.serviceProvider.create_login_request_url(store.identityProvider, {}, (err, loginUrl, requestId) => {
|
store.serviceProvider.create_login_request_url(store.identityProvider, {}, (err, loginUrl, requestId) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('Cannot SAML 2 authenticate.', { err })
|
logger.error('Cannot SAML 2 authenticate.', { err })
|
||||||
@ -190,6 +207,10 @@ async function loadSettingsAndCreateProviders (
|
|||||||
|
|
||||||
res.redirect(loginUrl)
|
res.redirect(loginUrl)
|
||||||
})
|
})
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('Cannot create login request url.', { err })
|
||||||
|
return redirectOnError(res)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -256,39 +277,3 @@ async function buildUser (settingsManager, samlUser) {
|
|||||||
role: findInUser(samlUser, settings['role-property'])
|
role: findInUser(samlUser, settings['role-property'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function lazyLoadServiceCertificates (peertubeHelpers, storageManager) {
|
|
||||||
const { logger } = peertubeHelpers
|
|
||||||
|
|
||||||
let privateKey = await storageManager.getData('service-private-key')
|
|
||||||
let publicKey = await storageManager.getData('service-public-key')
|
|
||||||
|
|
||||||
if (!privateKey || !publicKey) {
|
|
||||||
logger.info('Generating public/private keys for SAML 2.')
|
|
||||||
|
|
||||||
return new Promise((res, rej) => {
|
|
||||||
const options = {
|
|
||||||
modulusLength: 2048,
|
|
||||||
publicKeyEncoding: {
|
|
||||||
type: 'spki',
|
|
||||||
format: 'pem'
|
|
||||||
},
|
|
||||||
privateKeyEncoding: {
|
|
||||||
type: 'pkcs8',
|
|
||||||
format: 'pem'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto.generateKeyPair('rsa', options, (err, publicKey, privateKey) => {
|
|
||||||
if (err) return rej(err)
|
|
||||||
|
|
||||||
Promise.all([
|
|
||||||
storageManager.storeData('service-private-key', privateKey),
|
|
||||||
storageManager.storeData('service-public-key', publicKey)
|
|
||||||
]).then(() => res({ publicKey, privateKey }))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return { privateKey, publicKey }
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user