From 1441feb667fd51adf4743b84bf6ddfd96a6270b6 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 14 Jan 2022 15:12:42 -0300 Subject: [PATCH] [NEW] Apple Login (#24060) Co-authored-by: Diego Sampaio --- app/apple/server/appleOauthRegisterService.ts | 76 +++++++++++++++ app/apple/server/startup.ts | 31 +------ app/apple/server/tokenHandler.js | 2 +- app/cors/server/cors.js | 4 +- app/ui-login/client/login/services.html | 23 +++-- client/lib/utils/createAnchor.ts | 4 +- client/templates.ts | 4 + .../login/AppleOauth/AppleOauthButton.tsx | 93 +++++++++++++++++++ definition/rest/v1/settings.ts | 2 +- package-lock.json | 6 ++ package.json | 1 + server/configuration/accounts_meld.js | 2 +- 12 files changed, 204 insertions(+), 44 deletions(-) create mode 100644 app/apple/server/appleOauthRegisterService.ts create mode 100644 client/views/login/AppleOauth/AppleOauthButton.tsx diff --git a/app/apple/server/appleOauthRegisterService.ts b/app/apple/server/appleOauthRegisterService.ts new file mode 100644 index 00000000000..11753235a9b --- /dev/null +++ b/app/apple/server/appleOauthRegisterService.ts @@ -0,0 +1,76 @@ +import { KJUR } from 'jsrsasign'; +import { ServiceConfiguration } from 'meteor/service-configuration'; + +import { CustomOAuth } from '../../custom-oauth/server/custom_oauth_server'; +import { settings, settingsRegistry } from '../../settings/server'; + +const config = { + serverURL: 'https://appleid.apple.com', + tokenPath: '/auth/token', + scope: 'name email', + mergeUsers: true, + accessTokenParam: 'access_token', + loginStyle: 'popup', +}; + +new CustomOAuth('apple', config); + +settingsRegistry.addGroup('OAuth', function () { + this.section('Apple', function () { + this.add('Accounts_OAuth_Apple', false, { type: 'boolean', public: true }); + + this.add('Accounts_OAuth_Apple_id', '', { type: 'string', public: true }); + this.add('Accounts_OAuth_Apple_secretKey', '', { type: 'string', multiline: true }); + + this.add('Accounts_OAuth_Apple_iss', '', { type: 'string' }); + this.add('Accounts_OAuth_Apple_kid', '', { type: 'string' }); + }); +}); + +settings.watchMultiple( + [ + 'Accounts_OAuth_Apple', + 'Accounts_OAuth_Apple_id', + 'Accounts_OAuth_Apple_secretKey', + 'Accounts_OAuth_Apple_iss', + 'Accounts_OAuth_Apple_kid', + ], + ([enabled, clientId, serverSecret, iss, kid]) => { + if (!enabled) { + return ServiceConfiguration.configurations.remove({ + service: 'apple', + }); + } + + const HEADER = { + kid, + alg: 'ES256', + }; + + const tokenPayload = { + iss, + iat: Math.floor(Date.now() / 1000), + exp: Math.floor(Date.now() / 1000) + 300, + aud: 'https://appleid.apple.com', + sub: clientId, + }; + + const secret = KJUR.jws.JWS.sign(null, HEADER, tokenPayload, serverSecret as string); + + ServiceConfiguration.configurations.upsert( + { + service: 'apple', + }, + { + $set: { + // We'll hide this button on Web Client + showButton: false, + secret, + enabled: settings.get('Accounts_OAuth_Apple'), + loginStyle: 'popup', + clientId, + }, + }, + ); + }, +); diff --git a/app/apple/server/startup.ts b/app/apple/server/startup.ts index 3a655e6f3db..d4b3d92958a 100644 --- a/app/apple/server/startup.ts +++ b/app/apple/server/startup.ts @@ -1,30 +1 @@ -import { ServiceConfiguration } from 'meteor/service-configuration'; - -import { settings, settingsRegistry } from '../../settings/server'; - -settingsRegistry.addGroup('OAuth', function () { - this.section('Apple', function () { - this.add('Accounts_OAuth_Apple', false, { type: 'boolean', public: true }); - }); -}); - -settings.watch('Accounts_OAuth_Apple', (enabled) => { - if (!enabled) { - return ServiceConfiguration.configurations.remove({ - service: 'apple', - }); - } - - ServiceConfiguration.configurations.upsert( - { - service: 'apple', - }, - { - $set: { - // We'll hide this button on Web Client - showButton: false, - enabled: settings.get('Accounts_OAuth_Apple'), - }, - }, - ); -}); +import './appleOauthRegisterService'; diff --git a/app/apple/server/tokenHandler.js b/app/apple/server/tokenHandler.js index dcef12a5503..c756e198594 100644 --- a/app/apple/server/tokenHandler.js +++ b/app/apple/server/tokenHandler.js @@ -25,7 +25,7 @@ const isValidAppleJWT = (identityToken, header) => { } }; -export const handleIdentityToken = ({ identityToken, fullName, email }) => { +export const handleIdentityToken = ({ identityToken, fullName = {}, email }) => { check(identityToken, String); check(fullName, Match.Maybe(Object)); check(email, Match.Maybe(String)); diff --git a/app/cors/server/cors.js b/app/cors/server/cors.js index 414f8b85463..5f4e9db2a34 100644 --- a/app/cors/server/cors.js +++ b/app/cors/server/cors.js @@ -35,7 +35,7 @@ WebApp.rawConnectHandlers.use(function (req, res, next) { ] .filter(Boolean) .join(' '); - + const external = [settings.get('Accounts_OAuth_Apple') && 'https://appleid.cdn-apple.com'].filter(Boolean).join(' '); res.setHeader( 'Content-Security-Policy', [ @@ -45,7 +45,7 @@ WebApp.rawConnectHandlers.use(function (req, res, next) { 'frame-src *', 'img-src * data: blob:', 'media-src * data:', - `script-src 'self' 'unsafe-eval' ${inlineHashes} ${cdn_prefixes}`, + `script-src 'self' 'unsafe-eval' ${inlineHashes} ${cdn_prefixes} ${external}`, `style-src 'self' 'unsafe-inline' ${cdn_prefixes}`, ].join('; '), ); diff --git a/app/ui-login/client/login/services.html b/app/ui-login/client/login/services.html index bb19c56e00d..cc013fc5162 100644 --- a/app/ui-login/client/login/services.html +++ b/app/ui-login/client/login/services.html @@ -1,9 +1,18 @@ -