-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: tweak sign-in page design (#6774)
* feat: simplify sign-in page * redid styling, add brandName & providersLayout * edit some styling * remove default value * tweak * tweak * tweak logos * Update signin.tsx --------- Co-authored-by: Thang Vu <hi@thvu.dev>
- Loading branch information
1 parent
c4ad77b
commit 9af5887
Showing
112 changed files
with
837 additions
and
624 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 |
---|---|---|
@@ -1,7 +1,159 @@ | ||
import { SvelteKitAuth } from "@auth/sveltekit" | ||
import GitHub from "@auth/core/providers/github" | ||
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private" | ||
import Credentials from "@auth/core/providers/credentials" | ||
import Facebook from "@auth/core/providers/facebook" | ||
import Auth0 from "@auth/core/providers/auth0" | ||
import Discord from "@auth/core/providers/discord" | ||
import Email from "@auth/core/providers/email" | ||
import Google from "@auth/core/providers/google" | ||
import Twitter from "@auth/core/providers/twitter" | ||
import LinkedIn from "@auth/core/providers/linkedin" | ||
import Instagram from "@auth/core/providers/instagram" | ||
import Okta from "@auth/core/providers/okta" | ||
import Apple from "@auth/core/providers/apple" | ||
import Slack from "@auth/core/providers/slack" | ||
import Twitch from "@auth/core/providers/twitch" | ||
import Cognito from "@auth/core/providers/cognito" | ||
import AzureAD from "@auth/core/providers/azure-ad" | ||
import Reddit from "@auth/core/providers/reddit" | ||
import Spotify from "@auth/core/providers/spotify" | ||
import { | ||
GITHUB_ID, | ||
GITHUB_SECRET, | ||
FACEBOOK_ID, | ||
FACEBOOK_SECRET, | ||
AUTH0_ID, | ||
AUTH0_SECRET, | ||
AUTH0_ISSUER, | ||
DISCORD_ID, | ||
DISCORD_SECRET, | ||
GOOGLE_ID, | ||
GOOGLE_SECRET, | ||
TWITTER_ID, | ||
TWITTER_SECRET, | ||
LINKEDIN_ID, | ||
LINKEDIN_SECRET, | ||
INSTAGRAM_ID, | ||
INSTAGRAM_SECRET, | ||
OKTA_ID, | ||
OKTA_SECRET, | ||
OKTA_ISSUER, | ||
APPLE_ID, | ||
APPLE_SECRET, | ||
SLACK_ID, | ||
SLACK_SECRET, | ||
TWITCH_ID, | ||
TWITCH_SECRET, | ||
COGNITO_ID, | ||
COGNITO_SECRET, | ||
COGNITO_ISSUER, | ||
AZURE_AD_ID, | ||
AZURE_AD_SECRET, | ||
REDDIT_ID, | ||
REDDIT_SECRET, | ||
SPOTIFY_ID, | ||
SPOTIFY_SECRET, | ||
} from "$env/static/private" | ||
import { TestAdapter } from "$lib/adapter" | ||
|
||
const db: Record<string, any> = {} | ||
|
||
const adapter = TestAdapter({ | ||
getItem(key) { | ||
return db[key] | ||
}, | ||
setItem: function (key: string, value: string): Promise<void> { | ||
db[key] = value | ||
return Promise.resolve() | ||
}, | ||
deleteItems: function (...keys: string[]): Promise<void> { | ||
keys.forEach((key) => delete db[key]) | ||
return Promise.resolve() | ||
}, | ||
}) | ||
export const handle = SvelteKitAuth({ | ||
providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })], | ||
adapter, | ||
session: { | ||
strategy: "jwt", | ||
}, | ||
providers: [ | ||
Email({ server: "smtp://127.0.0.1:1025?tls.rejectUnauthorized=false" }), | ||
Credentials({ | ||
credentials: { password: { label: "Password", type: "password" } }, | ||
async authorize(credentials) { | ||
if (credentials.password !== "pw") return null | ||
return { | ||
name: "Fill Murray", | ||
email: "bill@fillmurray.com", | ||
image: "https://www.fillmurray.com/64/64", | ||
id: "1", | ||
foo: "", | ||
} | ||
}, | ||
}), | ||
Google({ | ||
clientId: GOOGLE_ID, | ||
clientSecret: GOOGLE_SECRET, | ||
}), | ||
Facebook({ clientId: FACEBOOK_ID, clientSecret: FACEBOOK_SECRET }), | ||
GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET }), | ||
Discord({ | ||
clientId: DISCORD_ID, | ||
clientSecret: DISCORD_SECRET, | ||
}), | ||
Twitter({ | ||
clientId: TWITTER_ID, | ||
clientSecret: TWITTER_SECRET, | ||
}), | ||
Slack({ | ||
clientId: SLACK_ID, | ||
clientSecret: SLACK_SECRET, | ||
}), | ||
LinkedIn({ | ||
clientId: LINKEDIN_ID, | ||
clientSecret: LINKEDIN_SECRET, | ||
}), | ||
Okta({ | ||
clientId: OKTA_ID, | ||
clientSecret: OKTA_SECRET, | ||
issuer: OKTA_ISSUER, | ||
}), | ||
Apple({ | ||
clientId: APPLE_ID, | ||
clientSecret: APPLE_SECRET, | ||
}), | ||
Auth0({ | ||
clientId: AUTH0_ID, | ||
clientSecret: AUTH0_SECRET, | ||
issuer: AUTH0_ISSUER, | ||
}), | ||
Spotify({ | ||
clientId: SPOTIFY_ID, | ||
clientSecret: SPOTIFY_SECRET, | ||
}), | ||
Instagram({ | ||
clientId: INSTAGRAM_ID, | ||
clientSecret: INSTAGRAM_SECRET, | ||
}), | ||
Cognito({ | ||
clientId: COGNITO_ID, | ||
clientSecret: COGNITO_SECRET, | ||
issuer: COGNITO_ISSUER, | ||
}), | ||
Twitch({ | ||
clientId: TWITCH_ID, | ||
clientSecret: TWITCH_SECRET, | ||
}), | ||
Reddit({ | ||
clientId: REDDIT_ID, | ||
clientSecret: REDDIT_SECRET, | ||
}), | ||
AzureAD({ | ||
clientId: AZURE_AD_ID, | ||
clientSecret: AZURE_AD_SECRET, | ||
}), | ||
], | ||
theme: { | ||
logo: "https://authjs.dev/img/logo/logo-sm.webp", | ||
}, | ||
}) |
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,186 @@ | ||
/** | ||
* Mock adapter for testing | ||
*/ | ||
|
||
import type { | ||
Adapter, | ||
AdapterUser, | ||
AdapterAccount, | ||
AdapterSession, | ||
} from "@auth/core/adapters" | ||
import type { Awaitable } from "@auth/core/types" | ||
|
||
export const options = { | ||
baseKeyPrefix: "", | ||
accountKeyPrefix: "user:account:", | ||
accountByUserIdPrefix: "user:account:by-user-id:", | ||
emailKeyPrefix: "user:email:", | ||
sessionKeyPrefix: "user:session:", | ||
sessionByUserIdKeyPrefix: "user:session:by-user-id:", | ||
userKeyPrefix: "user:", | ||
verificationTokenKeyPrefix: "user:token:", | ||
} | ||
|
||
export type DB = { | ||
getItem: (key: string) => Awaitable<any> | ||
setItem: (key: string, value: string) => Awaitable<void> | ||
deleteItems: (...keys: string[]) => Awaitable<void> | ||
} | ||
|
||
export function TestAdapter(client: DB): Adapter { | ||
const { baseKeyPrefix } = options | ||
const accountKeyPrefix = baseKeyPrefix + options.accountKeyPrefix | ||
const accountByUserIdPrefix = baseKeyPrefix + options.accountByUserIdPrefix | ||
const emailKeyPrefix = baseKeyPrefix + options.emailKeyPrefix | ||
const sessionKeyPrefix = baseKeyPrefix + options.sessionKeyPrefix | ||
const sessionByUserIdKeyPrefix = | ||
baseKeyPrefix + options.sessionByUserIdKeyPrefix | ||
const userKeyPrefix = baseKeyPrefix + options.userKeyPrefix | ||
const verificationTokenKeyPrefix = | ||
baseKeyPrefix + options.verificationTokenKeyPrefix | ||
|
||
const setObjectAsJson = async (key: string, obj: any) => | ||
await client.setItem(key, JSON.stringify(obj)) | ||
|
||
const setAccount = async (id: string, account: AdapterAccount) => { | ||
const accountKey = accountKeyPrefix + id | ||
await setObjectAsJson(accountKey, account) | ||
await client.setItem(accountByUserIdPrefix + account.userId, accountKey) | ||
return account | ||
} | ||
|
||
const getAccount = async (id: string) => { | ||
const account = await client.getItem(accountKeyPrefix + id) | ||
if (!account) return null | ||
return account | ||
} | ||
|
||
const setSession = async ( | ||
id: string, | ||
session: AdapterSession | ||
): Promise<AdapterSession> => { | ||
const sessionKey = sessionKeyPrefix + id | ||
await setObjectAsJson(sessionKey, session) | ||
await client.setItem(sessionByUserIdKeyPrefix + session.userId, sessionKey) | ||
return session | ||
} | ||
|
||
const getSession = async (id: string) => { | ||
const session = await client.getItem(sessionKeyPrefix + id) | ||
if (!session) return null | ||
return session | ||
} | ||
|
||
const setUser = async ( | ||
id: string, | ||
user: AdapterUser | ||
): Promise<AdapterUser> => { | ||
await setObjectAsJson(userKeyPrefix + id, user) | ||
await client.setItem(`${emailKeyPrefix}${user.email as string}`, id) | ||
return user | ||
} | ||
|
||
const getUser = async (id: string) => { | ||
const user = await client.getItem(userKeyPrefix + id) | ||
if (!user) return null | ||
return user | ||
} | ||
|
||
return { | ||
async createUser(user) { | ||
const id = crypto.randomUUID() | ||
// TypeScript thinks the emailVerified field is missing | ||
// but all fields are copied directly from user, so it's there | ||
return await setUser(id, { ...user, id }) | ||
}, | ||
getUser, | ||
async getUserByEmail(email) { | ||
const userId = await client.getItem(emailKeyPrefix + email) | ||
if (!userId) { | ||
return null | ||
} | ||
return await getUser(userId) | ||
}, | ||
async getUserByAccount(account) { | ||
const dbAccount = await getAccount( | ||
`${account.provider}:${account.providerAccountId}` | ||
) | ||
if (!dbAccount) return null | ||
return await getUser(dbAccount.userId) | ||
}, | ||
async updateUser(updates) { | ||
const userId = updates.id as string | ||
const user = await getUser(userId) | ||
return await setUser(userId, { ...(user as AdapterUser), ...updates }) | ||
}, | ||
async linkAccount(account) { | ||
const id = `${account.provider}:${account.providerAccountId}` | ||
return await setAccount(id, { ...account, id }) | ||
}, | ||
createSession: (session) => setSession(session.sessionToken, session), | ||
async getSessionAndUser(sessionToken) { | ||
const session = await getSession(sessionToken) | ||
if (!session) return null | ||
const user = await getUser(session.userId) | ||
if (!user) return null | ||
return { session, user } | ||
}, | ||
async updateSession(updates) { | ||
const session = await getSession(updates.sessionToken) | ||
if (!session) return null | ||
return await setSession(updates.sessionToken, { ...session, ...updates }) | ||
}, | ||
async deleteSession(sessionToken) { | ||
await client.deleteItems(sessionKeyPrefix + sessionToken) | ||
}, | ||
async createVerificationToken(verificationToken) { | ||
await setObjectAsJson( | ||
verificationTokenKeyPrefix + | ||
verificationToken.identifier + | ||
":" + | ||
verificationToken.token, | ||
verificationToken | ||
) | ||
return verificationToken | ||
}, | ||
async useVerificationToken(verificationToken) { | ||
const tokenKey = | ||
verificationTokenKeyPrefix + | ||
verificationToken.identifier + | ||
":" + | ||
verificationToken.token | ||
|
||
const token = await client.getItem(tokenKey) | ||
if (!token) return null | ||
|
||
await client.deleteItems(tokenKey) | ||
return token | ||
}, | ||
async unlinkAccount(account) { | ||
const id = `${account.provider}:${account.providerAccountId}` | ||
const dbAccount = await getAccount(id) | ||
if (!dbAccount) return | ||
const accountKey = `${accountKeyPrefix}${id}` | ||
await client.deleteItems( | ||
accountKey, | ||
`${accountByUserIdPrefix} + ${dbAccount.userId as string}` | ||
) | ||
}, | ||
async deleteUser(userId) { | ||
const user = await getUser(userId) | ||
if (!user) return | ||
const accountByUserKey = accountByUserIdPrefix + userId | ||
const accountKey = await client.getItem(accountByUserKey) | ||
const sessionByUserIdKey = sessionByUserIdKeyPrefix + userId | ||
const sessionKey = await client.getItem(sessionByUserIdKey) | ||
await client.deleteItems( | ||
userKeyPrefix + userId, | ||
`${emailKeyPrefix}${user.email as string}`, | ||
accountKey as string, | ||
accountByUserKey, | ||
sessionKey as string, | ||
sessionByUserIdKey | ||
) | ||
}, | ||
} | ||
} |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
9af5887
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
auth-docs – ./docs
next-auth-docs-m1mt.vercel.app
auth-docs-git-main-authjs.vercel.app
auth-docs-authjs.vercel.app
www.authjs.dev
sveltekit.authjs.dev
errors.authjs.dev
adapters.authjs.dev
warnings.authjs.dev
authjs.dev
providers.authjs.dev