-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented authentication to strava. Implemented storage of token da…
…ta as encrypted session cookies.
- Loading branch information
1 parent
2008db9
commit 08ca0b4
Showing
13 changed files
with
219 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { redirect } from 'next/navigation'; | ||
import { login } from '@/lib'; | ||
|
||
export const GET = async (req: Request) => { | ||
// Get the auth code and scope from the query string | ||
const url = new URL(req.url); | ||
const params = new URLSearchParams(url.search); | ||
const error = params.get("error"); | ||
const authCode = params.get("code"); | ||
const scope = params.get("scope"); | ||
if (error || !authCode) { | ||
console.error("error", error); | ||
redirect("/login/error"); | ||
} | ||
if (scope !== "read,activity:read_all") { | ||
console.error("scope", scope); | ||
redirect("/login/error"); | ||
} | ||
|
||
// Exchange the auth code for an access token | ||
const token_response = await fetch("https://www.strava.com/oauth/token", { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
client_id: process.env.CLIENT_ID, | ||
client_secret: process.env.CLIENT_SECRET, | ||
code: authCode, | ||
grant_type: "authorization_code", | ||
}), | ||
}); | ||
const token_data = await token_response.json(); | ||
console.log("token_data", token_data); | ||
await login(token_data); | ||
redirect(`/user/${token_data.athlete.id}?first_name=${token_data.athlete.firstname}`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react' | ||
|
||
const page = () => { | ||
return ( | ||
<h1>Login was unsuccessful.</h1> | ||
) | ||
} | ||
|
||
export default page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from "react"; | ||
import Link from "next/link"; | ||
|
||
const redirectUri = "http://localhost:3000/api/exchange_token"; | ||
const stravaUrl = `http://www.strava.com/oauth/authorize?client_id=${process.env.CLIENT_ID}&response_type=code&redirect_uri=${redirectUri}&approval_prompt=force&scope=activity:read_all`; | ||
|
||
const page = () => { | ||
return ( | ||
<> | ||
<h1>Welcome to VO2 Max Calculator</h1> | ||
<Link className="btn btn-primary" href={stravaUrl}> | ||
Login to Strava | ||
</Link> | ||
</> | ||
); | ||
}; | ||
|
||
export default page; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react' | ||
|
||
const page = () => { | ||
return ( | ||
<h1>Successfully logged in</h1> | ||
) | ||
} | ||
|
||
export default page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from "react"; | ||
import { getSession } from "@/lib"; | ||
|
||
const Greeting = () => { | ||
return <h1>Welcome</h1>; | ||
}; | ||
|
||
const page = async () => { | ||
const session = await getSession(); | ||
return( | ||
<> | ||
{Greeting()} | ||
<pre>{JSON.stringify(session, null, 2)}</pre> | ||
</> | ||
) | ||
}; | ||
|
||
export default page; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { SignJWT, jwtVerify } from "jose"; | ||
import { cookies } from "next/headers"; | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
const secretKey = "secret"; | ||
const key = new TextEncoder().encode(secretKey); | ||
|
||
export async function encrypt(payload: any) { | ||
return await new SignJWT(payload) | ||
.setProtectedHeader({ alg: "HS256" }) | ||
.setIssuedAt() | ||
.setExpirationTime("15 minutes from now") | ||
.sign(key); | ||
} | ||
|
||
export async function decrypt(input: string): Promise<any> { | ||
const { payload } = await jwtVerify(input, key, { | ||
algorithms: ["HS256"], | ||
}); | ||
return payload; | ||
} | ||
|
||
export async function login(userData: any) { | ||
const expires = new Date(Date.now() + 20 * 60 * 1000); | ||
const session = await encrypt({ userData, expires }); | ||
cookies().set("session", session, { expires, httpOnly: true }); | ||
} | ||
|
||
export async function logout() { | ||
cookies().set("session", "", { expires: new Date(0) }); | ||
} | ||
|
||
export async function getSession() { | ||
const session = cookies().get("session")?.value; | ||
if (!session) return null; | ||
return await decrypt(session); | ||
} | ||
|
||
export async function updateSession(request: NextRequest) { | ||
const session = request.cookies.get("session")?.value; | ||
if (!session) return null; | ||
|
||
const parsed = await decrypt(session); | ||
parsed.expires = new Date(Date.now() + 20 * 60 * 1000); | ||
const res = NextResponse.next(); | ||
res.cookies.set({ | ||
name: "session", | ||
value: await encrypt(parsed), | ||
expires: parsed.expires, | ||
httpOnly: true, | ||
}); | ||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { NextRequest } from 'next/server'; | ||
import { updateSession } from './lib'; | ||
|
||
export async function middleware(request: NextRequest) { | ||
return await updateSession(request); | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.