Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: twin-te/callback-handler
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.1.0
Choose a base ref
...
head repository: twin-te/callback-handler
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 8 commits
  • 8 files changed
  • 1 contributor

Commits on Mar 30, 2021

  1. Copy the full SHA
    fb744d2 View commit details
  2. add: urlencoded middleware

    SIY1121 committed Mar 30, 2021
    Copy the full SHA
    6edd892 View commit details
  3. update: apple callback

    SIY1121 committed Mar 30, 2021
    Copy the full SHA
    96983f8 View commit details

Commits on Apr 1, 2021

  1. fix: provider transform

    SIY1121 committed Apr 1, 2021
    Copy the full SHA
    c4f2f53 View commit details

Commits on Apr 2, 2021

  1. update: same-site none

    SIY1121 committed Apr 2, 2021
    Copy the full SHA
    e6ab32f View commit details
  2. Copy the full SHA
    1404b4d View commit details

Commits on Apr 12, 2021

  1. add: google idtoken endpoint

    SIY1121 committed Apr 12, 2021
    Copy the full SHA
    84f675d View commit details
  2. fix: tmp twitter

    SIY1121 committed Apr 12, 2021
    Copy the full SHA
    3f9715d View commit details
Showing with 122 additions and 23 deletions.
  1. +2 −1 package.json
  2. +8 −13 src/handlers/auth.ts
  3. +26 −0 src/handlers/idToken.ts
  4. +5 −1 src/index.ts
  5. +3 −2 src/passport.ts
  6. +18 −4 src/services/userService.ts
  7. +20 −0 src/utils.ts
  8. +40 −2 yarn.lock
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -34,10 +34,11 @@
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-session": "^1.17.1",
"google-auth-library": "^7.0.4",
"passport": "^0.4.1",
"passport-apple": "^1.1.1",
"passport-google-oauth": "^2.0.0",
"passport-twitter": "^1.0.4",
"protobufjs": "^6.10.2"
"protobufjs": "github:iFwu/protobuf.js"
}
}
21 changes: 8 additions & 13 deletions src/handlers/auth.ts
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ import { Request, Response } from 'express';
import passport from 'passport';
import { sessionService } from '../services/sessionService';
import { userService } from '../services/userService';
import { applySessionCookie } from '../utils';

const cookieName = process.env.COOKIE_NAME ?? 'twinte_session';

@@ -65,27 +66,21 @@ export async function handleAuthCallback(req: Request, res: Response) {
new Promise<void>((resolve, reject) => req.session?.destroy((err) => (err ? reject(err) : resolve()))))();

if (!req.user) {
res.sendStatus(400);
res.status(400).send(`
<p>BadRequest</p>
<button onclick="location.reload()">再読み込み</button>
`); // twitterが上手く動かない対応一時処理
return;
}

const user = await userService.getOrCreateUser({ provider: provider, socialId: req.user.id });
const { session, cookieOptions } = await sessionService.startSession({ userId: user.id });
const expiredDate = fromUnixTime(session.expiredAt.seconds as number);

const callbackUrl = req.cookies['twinte_auth_callback'] || 'https://www.twinte.net';

res.cookie(cookieName, session.sessionId, {
expires: expiredDate,
secure: cookieOptions.secure,
httpOnly: true,
sameSite: 'lax',
});
await applySessionCookie(provider, req.user.id, res);

// cookie cleanup
res.clearCookie('connect.sid');
res.clearCookie('twinte_auth_callback');

const callbackUrl = req.cookies['twinte_auth_callback'] || 'https://app.twinte.net';

res.redirect(callbackUrl);
res.send();
});
26 changes: 26 additions & 0 deletions src/handlers/idToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { OAuth2Client } from 'google-auth-library';
import { Request, Response } from 'express';
import { applySessionCookie } from '../utils';

const client = new OAuth2Client(process.env.GOOGLE_CLIENT_ID!);

export async function handleGoogleIdToken(req: Request, res: Response) {
try {
const ticket = await client.verifyIdToken({
idToken: req.query.token as string,
audience: process.env.GOOGLE_CLIENT_ID!,
});
const payload = ticket.getPayload();
const userid = payload?.sub;

if (userid) {
await applySessionCookie('google', userid, res);
res.send(200);
} else {
res.send(400);
}
} catch (e) {
console.error(e);
res.send(400);
}
}
6 changes: 5 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -7,9 +7,12 @@ import { handleAuth, handleAuthCallback, handleLogout } from './handlers/auth';
import { configurePassport } from './passport';
import cookieParser from 'cookie-parser';
import passport from 'passport';
import { handleGoogleIdToken } from './handlers/idToken';

const app = express();
app.use(cookieParser());
app.use(express.urlencoded({ extended: true }));

configurePassport();
app.use(
session({
@@ -24,7 +27,8 @@ app.use(passport.initialize());
app.use(passport.session());
app.get('/logout', handleLogout);
app.get('/:provider', handleAuth);
app.get('/:provider/callback', handleAuthCallback);
app.use('/:provider/callback', handleAuthCallback);
app.use('/google/idToken', handleGoogleIdToken);

app.listen(process.env.PORT ? parseInt(process.env.PORT) : 3001);

5 changes: 3 additions & 2 deletions src/passport.ts
Original file line number Diff line number Diff line change
@@ -40,11 +40,12 @@ export function configurePassport() {
teamID: process.env.APPLE_TEAM_ID!,
keyID: process.env.APPLE_KEY_ID!,
scope: '',
privateKeyString: process.env.APPLE_PRIVATE_KEY,
privateKeyString: process.env.APPLE_PRIVATE_KEY!.replace(/\\n/gm, '\n'),
callbackURL: `${process.env.HOST_URL}/apple/callback`,
passReqToCallback: false,
},
(_accessToken, _refreshToken, _idToken, profile, cb) => {
cb(null, { id: profile.id });
cb(null, { id: _idToken.sub });
},
),
);
22 changes: 18 additions & 4 deletions src/services/userService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { UserService } from '../../generated/services/user';
import { UserService, Provider as GProvider } from '../../generated/services/user';
import { Provider } from '../models/provider';
import { createClient, wrapGrpcRequestMethodFactory } from './grpc';

@@ -11,7 +11,21 @@ const userServiceClient = createClient(
const methodWrapper = wrapGrpcRequestMethodFactory(userServiceClient);

export const userService = {
getOrCreateUser: methodWrapper<typeof userServiceClient.getOrCreateUser, { provider: Provider; socialId: string }>(
userServiceClient.getOrCreateUser,
),
getOrCreateUser: methodWrapper(userServiceClient.getOrCreateUser, {
to: (req: { provider: Provider; socialId: string }) => ({
provider: toGrpcProvider(req.provider),
socialId: req.socialId,
}),
}),
};

function toGrpcProvider(p: Provider): GProvider {
switch (p) {
case 'google':
return GProvider.Google;
case 'twitter':
return GProvider.Twitter;
case 'apple':
return GProvider.Apple;
}
}
20 changes: 20 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Provider } from './models/provider';
import { Response } from 'express';
import { userService } from './services/userService';
import { sessionService } from './services/sessionService';
import { fromUnixTime } from 'date-fns';

const cookieName = process.env.COOKIE_NAME ?? 'twinte_session';

export async function applySessionCookie(provider: Provider, socialId: string, res: Response) {
const user = await userService.getOrCreateUser({ provider: provider, socialId: socialId });
const { session, cookieOptions } = await sessionService.startSession({ userId: user.id });
const expiredDate = fromUnixTime(session.expiredAt.seconds as number);

res.cookie(cookieName, session.sessionId, {
expires: expiredDate,
secure: cookieOptions.secure,
httpOnly: true,
sameSite: 'none',
});
}
42 changes: 40 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -182,7 +182,7 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==

"@types/long@^4.0.1":
"@types/long@^4.0.0", "@types/long@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==
@@ -202,6 +202,11 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e"
integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==

"@types/node@^10.1.0":
version "10.17.56"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.56.tgz#010c9e047c3ff09ddcd11cbb6cf5912725cdc2b3"
integrity sha512-LuAa6t1t0Bfw4CuSR0UITsm1hP17YL+u82kfHGrHUWdhlBtH7sa7jGY5z7glGaIj/WDYDkRtgGd+KCjCzxBW1w==

"@types/node@^13.7.0":
version "13.13.48"
resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.48.tgz#46a3df718aed5217277f2395a682e055a487e341"
@@ -1085,6 +1090,21 @@ google-auth-library@^6.1.1:
jws "^4.0.0"
lru-cache "^6.0.0"

google-auth-library@^7.0.4:
version "7.0.4"
resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-7.0.4.tgz#610cb010de71435dca47dfbe8dc7fbff23055d2c"
integrity sha512-o8irYyeijEiecTXeoEe8UKNEzV1X+uhR4b2oNdapDMZixypp0J+eHimGOyx5Joa3UAeokGngdtDLXtq9vDqG2Q==
dependencies:
arrify "^2.0.0"
base64-js "^1.3.0"
ecdsa-sig-formatter "^1.0.11"
fast-text-encoding "^1.0.0"
gaxios "^4.0.0"
gcp-metadata "^4.2.0"
gtoken "^5.0.4"
jws "^4.0.0"
lru-cache "^6.0.0"

google-p12-pem@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e"
@@ -1637,7 +1657,7 @@ progress@^2.0.0:
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==

protobufjs@^6.10.2, protobufjs@^6.8.6:
protobufjs@^6.8.6:
version "6.10.2"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.2.tgz#b9cb6bd8ec8f87514592ba3fdfd28e93f33a469b"
integrity sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==
@@ -1656,6 +1676,24 @@ protobufjs@^6.10.2, protobufjs@^6.8.6:
"@types/node" "^13.7.0"
long "^4.0.0"

"protobufjs@github:iFwu/protobuf.js":
version "6.8.8"
resolved "https://codeload.github.com/iFwu/protobuf.js/tar.gz/bec020a0071f60a9425efb0d237b84be7ef9e054"
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
"@protobufjs/codegen" "^2.0.4"
"@protobufjs/eventemitter" "^1.1.0"
"@protobufjs/fetch" "^1.1.0"
"@protobufjs/float" "^1.0.2"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/path" "^1.1.2"
"@protobufjs/pool" "^1.1.0"
"@protobufjs/utf8" "^1.1.0"
"@types/long" "^4.0.0"
"@types/node" "^10.1.0"
long "^4.0.0"

proxy-addr@~2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"