-
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.
Add support for authenticating the CLI and switching accounts (#14)
- Loading branch information
Showing
11 changed files
with
189 additions
and
14 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,37 @@ | ||
import { URLS } from "@/constants"; | ||
|
||
export async function fulfillAuthRequest(id: string, token: string) { | ||
const resp = await fetch(`${URLS.api}/v1/graphql`, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
query: ` | ||
mutation FulfillAuthRequest($secret: String!, $id: String!, $token: String!) { | ||
fulfillAuthRequest(input: {secret: $secret, id: $id, token: $token}) { | ||
success | ||
source | ||
} | ||
} | ||
`, | ||
variables: { | ||
secret: "omNN-4K*GiHhqUH8-7mUB6Ecz8ZPBtcqH68V", | ||
id, | ||
token, | ||
}, | ||
}), | ||
}); | ||
|
||
const json = await resp.json(); | ||
|
||
if (json.errors) { | ||
throw new Error(json.errors[0].message); | ||
} | ||
|
||
if (!json.data.fulfillAuthRequest.success) { | ||
throw new Error("Failed to fulfill authentication request"); | ||
} | ||
|
||
return json.data.fulfillAuthRequest.source; | ||
} |
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,33 @@ | ||
import { URLS } from "@/constants"; | ||
|
||
export async function initAuthRequest(key: string, source: string) { | ||
const resp = await fetch(`${URLS.api}/v1/graphql`, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
query: ` | ||
mutation InitAutRequest($key: String!, $source: String = "browser") { | ||
initAuthRequest(input: {key: $key, source: $source}) { | ||
id | ||
challenge | ||
serverKey | ||
} | ||
} | ||
`, | ||
variables: { | ||
key, | ||
source, | ||
}, | ||
}), | ||
}); | ||
|
||
const json: any = await resp.json(); | ||
|
||
if (json.errors) { | ||
throw new Error(json.errors[0].message); | ||
} | ||
|
||
return json.data.initAuthRequest; | ||
} |
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 |
---|---|---|
@@ -1,12 +1,18 @@ | ||
import { handleAuth, handleLogin } from "@auth0/nextjs-auth0"; | ||
|
||
const authorizationParams = { | ||
audience: "https://api.replay.io", | ||
code_challenge_method: "S256", | ||
response_type: "code" as "code", | ||
scope: "openid profile offline_access", | ||
}; | ||
|
||
export default handleAuth({ | ||
login: handleLogin({ | ||
login: handleLogin({ authorizationParams }), | ||
switchAccount: handleLogin({ | ||
authorizationParams: { | ||
audience: "https://api.replay.io", | ||
code_challenge_method: "S256", | ||
response_type: "code", | ||
scope: "openid profile offline_access", | ||
...authorizationParams, | ||
prompt: "login", | ||
}, | ||
}), | ||
}); |
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,56 @@ | ||
import { COOKIES, URLS } from "@/constants"; | ||
import cookie from "cookie"; | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
import { getSession } from "@auth0/nextjs-auth0"; | ||
import { initAuthRequest } from "@/graphql/queries/initAuthRequest"; | ||
import { fulfillAuthRequest } from "@/graphql/queries/fulfillAuthRequest"; | ||
|
||
const getQueryValue = (query: string | string[] | undefined) => (Array.isArray(query) ? query[0] : query); | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const key = getQueryValue(req.query.key); | ||
const source = getQueryValue(req.query.source) || "browser"; | ||
|
||
try { | ||
if (key) { | ||
const { id } = await initAuthRequest(key, source); | ||
|
||
res.setHeader( | ||
"Set-Cookie", | ||
cookie.serialize(COOKIES.browserAuth, id, { | ||
secure: URLS.app.startsWith("https://"), | ||
httpOnly: true, | ||
path: "/", | ||
maxAge: 5 * 60 * 1000, | ||
}) | ||
); | ||
|
||
res.redirect("/login?returnTo=/api/browser/auth"); | ||
} else { | ||
const browserAuth = req.cookies[COOKIES.browserAuth]; | ||
|
||
if (!browserAuth) { | ||
res.statusCode = 400; | ||
res.statusMessage = "Missing cookie"; | ||
res.send(""); | ||
|
||
return; | ||
} | ||
|
||
const session = await getSession(req, res); | ||
if (session?.refreshToken) { | ||
const source = await fulfillAuthRequest(browserAuth, session.refreshToken); | ||
res.redirect(`/browser/authenticated?source=${source}`); | ||
} else { | ||
res.statusCode = 400; | ||
res.statusMessage = "Missing refresh token"; | ||
res.send(""); | ||
} | ||
} | ||
} catch (e: any) { | ||
console.error(e); | ||
|
||
res.statusCode = 500; | ||
res.send(""); | ||
} | ||
}; |
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,20 @@ | ||
import { EmptyLayout } from "@/components/EmptyLayout"; | ||
import { Message } from "@/components/Message"; | ||
import { ReplayLogo } from "@/components/ReplayLogo"; | ||
import React from "react"; | ||
|
||
export default function Page() { | ||
return ( | ||
<Message className="max-w-96 p-8 gap-8 text-center"> | ||
<ReplayLogo className="text-white min-w-20 min-h-20" /> | ||
<div className="font-bold text-xl"> | ||
Authentication Complete | ||
</div> | ||
<div> | ||
You have successfully logged in. You may close this window. | ||
</div> | ||
</Message> | ||
); | ||
}; | ||
|
||
Page.Layout = EmptyLayout; |
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