Skip to content

Instantly share code, notes, and snippets.

@PhantomKnight287
Created November 29, 2023 08:08
Show Gist options
  • Select an option

  • Save PhantomKnight287/4859e6c365653b680d69ffa046f56506 to your computer and use it in GitHub Desktop.

Select an option

Save PhantomKnight287/4859e6c365653b680d69ffa046f56506 to your computer and use it in GitHub Desktop.
Linkedin Oauth in a nestjs application.
import jose from 'node-jose';
const urlToGetLinkedInAccessToken =
'https://www.linkedin.com/oauth/v2/accessToken';
export type LinkedInUser = {
iss: string;
aud: string;
iat: number;
exp: number;
sub: string;
name: string;
given_name: string;
family_name: string;
picture: string;
email: string;
email_verified: string;
locale: string;
};
export async function getLinkedInVerificationKeyStructure() {
const req = await fetch('https://www.linkedin.com/oauth/openid/jwks');
if (!req.ok) throw new Error('Failed to fetch key from LinkedIn');
const data = (await req.json()) as {
keys: Array<{ kty: string; e: string; kid: string; n: string }>;
};
return data.keys;
}
export async function getAccessToken(code: string) {
const params = new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: `${process.env.APPLICATION_URL}/auth/oauth/redirect/linkedin`,
client_id: process.env.LINKEDIN_CLIENT_ID,
client_secret: process.env.LINKEDIN_CLIENT_SECRET,
});
const req = await fetch(
`${urlToGetLinkedInAccessToken}?${params.toString()}`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
},
);
if (!req.ok) throw new Error('Failed to get access token');
const data = (await req.json()) as {
access_token: string;
expires_in: number;
scope: string;
token_type: string;
id_token: string;
};
return data.id_token;
}
async handleLinkedInOauthRedirect(code: string, res: Response) {
const keys = await getLinkedInVerificationKeyStructure();
const accessToken = await getAccessToken(code);
const keyStore = jose.JWK.asKeyStore(keys);
const decodedToken = decode(accessToken) as LinkedInUser;
const key = (await keyStore).get(decodedToken['kid']);
await jose.JWS.createVerify(key).verify(accessToken);
const user = await createUserIfNotExists({
email: decodedToken.email,
name: decodedToken.name.replaceAll(' ', ' '),
});
const token = sign({ id: user.id }, process.env.JWT_SECRET);
return res.redirect(
`${process.env.HOST_URL}?token=${token}&userType=freelancer`,
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment