Fix SAML signature
This commit is contained in:
		| @ -1,3 +1,17 @@ | ||||
| # SAML2 auth plugin for 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 | ||||
|   }) | ||||
|  | ||||
|   registerSetting({ | ||||
|     name: 'sign-get-request', | ||||
|     label: 'Sign get request', | ||||
|     type: 'input-checkbox', | ||||
|     private: true, | ||||
|     default: false | ||||
|   }) | ||||
|  | ||||
|   registerSetting({ | ||||
|     name: 'auth-display-name', | ||||
|     label: 'Auth display name', | ||||
| @ -54,11 +46,33 @@ async function register ({ | ||||
|  | ||||
|   registerSetting({ | ||||
|     name: 'provider-certificate', | ||||
|     label: 'Identity provider certificate', | ||||
|     label: 'Identity provider certificate (PEM format)', | ||||
|     type: 'input-textarea', | ||||
|     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({ | ||||
|     name: 'username-property', | ||||
|     label: 'Username property', | ||||
| @ -145,7 +159,9 @@ async function loadSettingsAndCreateProviders ( | ||||
|     'client-id', | ||||
|     'sign-get-request', | ||||
|     'login-url', | ||||
|     'provider-certificate' | ||||
|     'provider-certificate', | ||||
|     'service-certificate', | ||||
|     'service-private-key' | ||||
|   ]) | ||||
|  | ||||
|   if (!settings['login-url']) { | ||||
| @ -158,12 +174,12 @@ async function loadSettingsAndCreateProviders ( | ||||
|     return | ||||
|   } | ||||
|  | ||||
|   const { publicKey: servicePublicKey, privateKey: servicePrivateKey } = await lazyLoadServiceCertificates(peertubeHelpers, storageManager) | ||||
|   logger.debug('Creating SAML service/identity instances.', { settings }) | ||||
|  | ||||
|   const serviceOptions = { | ||||
|     entity_id: settings['client-id'], | ||||
|     private_key: servicePrivateKey, | ||||
|     certificate: servicePublicKey, | ||||
|     private_key: settings['service-private-key'], | ||||
|     certificate: settings['service-certificate'], | ||||
|     assert_endpoint: store.assertUrl | ||||
|   } | ||||
|   store.serviceProvider = new saml2.ServiceProvider(serviceOptions) | ||||
| @ -182,6 +198,7 @@ async function loadSettingsAndCreateProviders ( | ||||
|     authName: 'saml2', | ||||
|     authDisplayName: () => store.authDisplayName, | ||||
|     onAuthRequest: async (req, res) => { | ||||
|       try { | ||||
|         store.serviceProvider.create_login_request_url(store.identityProvider, {}, (err, loginUrl, requestId) => { | ||||
|           if (err) { | ||||
|             logger.error('Cannot SAML 2 authenticate.', { err }) | ||||
| @ -190,6 +207,10 @@ async function loadSettingsAndCreateProviders ( | ||||
|  | ||||
|           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']) | ||||
|   } | ||||
| } | ||||
|  | ||||
| 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 } | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user