Skip to content
This repository was archived by the owner on Oct 26, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions src/controllers/authenticate.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,36 @@ export async function login(options, req, res) {
});
}

export async function socialLoginCallback(options, req, res) {
export async function socialLoginCallback(options, service, req, res) {
const { user } = req;

if (await user.isBanned()) {
throw new PermissionError('You have been banned.');
}

let script = '';
if (user.pendingActivation) {
script = `
var opener = window.opener;
if (opener) {
opener.postMessage({
pending: true,
socialAvatar: ${JSON.stringify(user.avatar)},
type: ${JSON.stringify(service)}
}, '*');
}
window.close();
`;
} else {
script = `
var opener = window.opener;
if (opener) {
opener.postMessage({ pending: false }, '*');
}
window.close();
`;
}

await refreshSession(res, req.uwaveHttp, user, {
...options,
session: 'cookie',
Expand All @@ -107,14 +130,41 @@ export async function socialLoginCallback(options, req, res) {
<meta charset="utf-8">
<title>Success</title>
</head>
<body>
<body style="background: #151515; color: #fff; font: 12pt 'Open Sans', sans-serif">
You can now close this window.
<script>close()</script>
<script>${script}</script>
</body>
</html>
`);
}

export async function socialLoginFinish(options, service, req, res) {
const { user } = req;
const sessionType = req.query.session === 'cookie' ? 'cookie' : 'token';

if (await user.isBanned()) {
throw new PermissionError('You have been banned.');
}

const { username } = req.body;

user.username = username;
user.pendingActivation = undefined;
await user.save();

const { token, socketToken } = await refreshSession(res, req.uwaveHttp, user, {
...options,
session: sessionType,
});

return toItemResponse(user, {
meta: {
jwt: sessionType === 'token' ? token : 'cookie',
socketToken,
},
});
}

export async function getSocketToken(req) {
const { user } = req;
const { authRegistry } = req.uwaveHttp;
Expand Down
9 changes: 8 additions & 1 deletion src/passport.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ export default function configurePassport(uw, options) {
});
}

async function googleLogin(accessToken, refreshToken, profile) {
return socialLogin(accessToken, refreshToken, {
id: profile.id,
photos: profile.photos,
});
}

async function serializeUser(user) {
return user.id;
}
Expand All @@ -36,7 +43,7 @@ export default function configurePassport(uw, options) {
callbackURL: '/auth/service/google/callback',
...options.auth.google,
scope: ['profile'],
}, callbackify(socialLogin)));
}, callbackify(googleLogin)));
}

passport.use('jwt', new JWTStrategy(options.secret, user => uw.getUser(user.id)));
Expand Down
9 changes: 7 additions & 2 deletions src/routes/authenticate.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,16 @@ export default function authenticateRoutes(api, options) {
passport.authenticate('google'),
route(controller.login.bind(null, options)),
)
// GET /auth/service/google/callback - Finish a social login using Google.
// GET /auth/service/google/callback - Receive social login data from Google.
.get(
'/service/google/callback',
passport.authenticate('google'),
route(controller.socialLoginCallback.bind(null, options)),
route(controller.socialLoginCallback.bind(null, options, 'google')),
)
// POST /auth/service/google/finish - Finish creating an account with Google.
.post(
'/service/google/finish',
route(controller.socialLoginFinish.bind(null, options, 'google')),
);
}

Expand Down