separate subject from identifier
This commit is contained in:
parent
fd197907ab
commit
817d3f3175
|
@ -9,9 +9,13 @@ OAUTH2__GET_TOKEN=
|
|||
OAUTH2__CLIENT_ID=
|
||||
# Client secret
|
||||
OAUTH2__CLIENT_SECRET=
|
||||
# OAuth2 scopes
|
||||
OAUTH2__SCOPES=openid profile
|
||||
|
||||
# Userinfo route
|
||||
USERINFO__ROUTE=
|
||||
# Identifier you'd like to use to link avatars with
|
||||
USERINFO__IDENTIFIER=preferred_username
|
||||
|
||||
# Prisma database URL
|
||||
DATABASE_URL="file:./data.db"
|
|
@ -27,6 +27,7 @@
|
|||
"type": "module",
|
||||
"dependencies": {
|
||||
"@fontsource-variable/inter": "^5.0.18",
|
||||
"@fontsource-variable/noto-sans-mono": "^5.0.20",
|
||||
"@prisma/client": "5.16.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,13 @@ const configuration = {
|
|||
},
|
||||
client: {
|
||||
id: process.env.OAUTH2__CLIENT_ID,
|
||||
secret: process.env.OAUTH2__CLIENT_SECRET
|
||||
secret: process.env.OAUTH2__CLIENT_SECRET,
|
||||
scopes: process.env.OAUTH2__SCOPES
|
||||
}
|
||||
},
|
||||
userinfo: {
|
||||
route: process.env.USERINFO__ROUTE
|
||||
route: process.env.USERINFO__ROUTE,
|
||||
identifier: process.env.USERINFO__IDENTIFIER
|
||||
}
|
||||
}
|
||||
export default configuration
|
|
@ -92,41 +92,44 @@ export async function getUserInfo(id: string) {
|
|||
})
|
||||
if (!tokenInfo) return
|
||||
|
||||
let userInfo
|
||||
|
||||
// check for cached userinfo
|
||||
if (userInfoCache.has(tokenInfo.owner))
|
||||
return userInfoCache.get(tokenInfo.owner)
|
||||
|
||||
userInfo = userInfoCache.get(tokenInfo.owner)
|
||||
else {
|
||||
let userInfoRequest = await fetchUserInfo(tokenInfo.token)
|
||||
if (!userInfoRequest.ok) {
|
||||
// assume that token has expired.
|
||||
// try fetching a new one
|
||||
if (!userInfoRequest.ok) {
|
||||
// assume that token has expired.
|
||||
// try fetching a new one
|
||||
|
||||
if (!tokenInfo.refreshToken) return // no refresh token. back out
|
||||
let token = await getNewToken({
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: tokenInfo.refreshToken
|
||||
})
|
||||
if (!tokenInfo.refreshToken) return // no refresh token. back out
|
||||
let token = await getNewToken({
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: tokenInfo.refreshToken
|
||||
})
|
||||
|
||||
if (!token) return // refresh failed. back out
|
||||
prisma.token.update({
|
||||
where: { id },
|
||||
data: {
|
||||
token: token.access_token,
|
||||
refreshToken: token.refresh_token
|
||||
}
|
||||
})
|
||||
if (!token) return // refresh failed. back out
|
||||
prisma.token.update({
|
||||
where: { id },
|
||||
data: {
|
||||
token: token.access_token,
|
||||
refreshToken: token.refresh_token
|
||||
}
|
||||
})
|
||||
|
||||
userInfoRequest = await fetchUserInfo(token.access_token)
|
||||
if (!userInfoRequest.ok) return // Give up
|
||||
userInfoRequest = await fetchUserInfo(token.access_token)
|
||||
if (!userInfoRequest.ok) return // Give up
|
||||
}
|
||||
|
||||
userInfo = await userInfoRequest.json()
|
||||
|
||||
// cache userinfo
|
||||
userInfoCache.set(tokenInfo.owner, userInfo)
|
||||
setTimeout(() => userInfoCache.delete(tokenInfo.owner), 60*60*1000)
|
||||
}
|
||||
|
||||
const userInfo = await userInfoRequest.json()
|
||||
|
||||
// cache userinfo
|
||||
userInfoCache.set(tokenInfo.owner, userInfo)
|
||||
setTimeout(() => userInfoCache.delete(tokenInfo.owner), 60*60*1000)
|
||||
|
||||
return userInfo as User
|
||||
return { ...userInfo, identifier: userInfo[configuration.userinfo.identifier] } as User
|
||||
}
|
||||
|
||||
export function deleteToken(id: string) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export interface User {
|
||||
name: string
|
||||
sub: string
|
||||
identifier: string
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import "@fontsource-variable/inter";
|
||||
import "@fontsource-variable/noto-sans-mono"
|
||||
import ava from "../assets/ava_icon.svg?raw"
|
||||
import type { User } from "$lib/types";
|
||||
export let data: { user?: User };
|
||||
|
@ -15,12 +16,14 @@
|
|||
--text: black;
|
||||
--link: #333;
|
||||
--background: white;
|
||||
--crust: #eee;
|
||||
}
|
||||
@media (prefers-color-scheme:dark) {
|
||||
:root {
|
||||
--text: white;
|
||||
--link: #aaa;
|
||||
--background: #111;
|
||||
--crust: #333;
|
||||
}
|
||||
}
|
||||
html {
|
||||
|
@ -54,6 +57,9 @@
|
|||
a {
|
||||
color: var(--link)
|
||||
}
|
||||
code {
|
||||
font-family: "Space Mono", monospace, monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -4,7 +4,41 @@
|
|||
export let data: {user: User};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
form {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
form > * {
|
||||
font-family: "Inter Variable", "Inter", sans-serif;
|
||||
}
|
||||
form > input[type="file"] {
|
||||
width: 100%;
|
||||
}
|
||||
form > input[type="submit"], form > input[type="file"] {
|
||||
padding: 0.5em 1em;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--link);
|
||||
color: var(--text);
|
||||
background-color: var(--crust);
|
||||
}
|
||||
form > input[type="file"]::file-selector-button {
|
||||
display: none;
|
||||
}
|
||||
form > label {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1>Hi, {data.user.name}</h1>
|
||||
<p>
|
||||
Your identifier is {data.user.sub}.
|
||||
The <code>sub</code> claim is set to <code>{data.user.sub}</code>.
|
||||
Your identifier is <code>{data.user.identifier}</code>.
|
||||
</p>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<label for="newAvatar">Set a new avatar:</label>
|
||||
<input type="file" accept="image/*" name="newAvatar">
|
||||
<input type="submit" value="Upload">
|
||||
</form>
|
Loading…
Reference in a new issue