-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
password reset and magic link #14
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
dotenv |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,9 @@ node_modules | |
/dist | ||
.wrangler | ||
|
||
# npm | ||
package-lock.json | ||
|
||
# OS | ||
.DS_Store | ||
Thumbs.db | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -7,16 +7,15 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signInWithPopup, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signInWithRedirect, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
getRedirectResult, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signInWithEmailAndPassword as _signInWithEmailAndPassword, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
createUserWithEmailAndPassword as _createUserWithEmailAndPassword, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
connectAuthEmulator, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type UserCredential, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type AuthProvider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} from 'firebase/auth'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { invalidate } from '$app/navigation'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { getApp } from 'firebase/app'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** re-export the official firebase/auth for convenience */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export * from 'firebase/auth'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let redirectResultPromise: Promise<UserCredential | null>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export function setupAuthClient(options: { emulatorHost?: string }) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -33,7 +32,7 @@ export function setupAuthClient(options: { emulatorHost?: string }) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Update the session cookie when the idToken changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auth.onIdTokenChanged(async (user) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (user) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateSession(await user.getIdToken()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateSession(await user.getIdToken(true)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -61,6 +60,20 @@ export async function signInWithTwitter() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await signInWithProvider(provider); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function signInWithEmailAndPassword(email: string, password: string) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const auth = getAuth(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const cred = await _signInWithEmailAndPassword(auth, email, password); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await updateSession(await cred.user.getIdToken()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return cred; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. エラーハンドリングの追加を推奨 メールパスワード認証にエラーハンドリングを追加することを推奨します: export async function signInWithEmailAndPassword(email: string, password: string) {
const auth = getAuth();
- const cred = await _signInWithEmailAndPassword(auth, email, password);
- await updateSession(await cred.user.getIdToken());
- return cred;
+ try {
+ const cred = await _signInWithEmailAndPassword(auth, email, password);
+ await updateSession(await cred.user.getIdToken());
+ return cred;
+ } catch (error: any) {
+ // Firebase Auth エラーコードに基づいてユーザーフレンドリーなメッセージを返す
+ switch (error.code) {
+ case 'auth/invalid-email':
+ throw new Error('メールアドレスの形式が正しくありません。');
+ case 'auth/user-disabled':
+ throw new Error('このアカウントは無効化されています。');
+ case 'auth/user-not-found':
+ case 'auth/wrong-password':
+ throw new Error('メールアドレスまたはパスワードが正しくありません。');
+ default:
+ throw new Error('ログインに失敗しました。しばらく経ってから再度お試しください。');
+ }
+ }
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function createUserWithEmailAndPassword(email: string, password: string) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const auth = getAuth(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const cred = await _createUserWithEmailAndPassword(auth, email, password); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await updateSession(await cred.user.getIdToken()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return cred; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. アカウント作成時のバリデーションとエラーハンドリングの追加を推奨 アカウント作成機能にバリデーションとエラーハンドリングを追加することを推奨します: export async function createUserWithEmailAndPassword(email: string, password: string) {
const auth = getAuth();
- const cred = await _createUserWithEmailAndPassword(auth, email, password);
- await updateSession(await cred.user.getIdToken());
- return cred;
+ // パスワードの強度チェック
+ if (password.length < 8) {
+ throw new Error('パスワードは8文字以上である必要があります。');
+ }
+ if (!/[A-Z]/.test(password)) {
+ throw new Error('パスワードは少なくとも1つの大文字を含む必要があります。');
+ }
+ if (!/[0-9]/.test(password)) {
+ throw new Error('パスワードは少なくとも1つの数字を含む必要があります。');
+ }
+
+ try {
+ const cred = await _createUserWithEmailAndPassword(auth, email, password);
+ await updateSession(await cred.user.getIdToken());
+ return cred;
+ } catch (error: any) {
+ switch (error.code) {
+ case 'auth/email-already-in-use':
+ throw new Error('このメールアドレスは既に使用されています。');
+ case 'auth/invalid-email':
+ throw new Error('メールアドレスの形式が正しくありません。');
+ case 'auth/operation-not-allowed':
+ throw new Error('メール/パスワードでの認証が有効になっていません。');
+ case 'auth/weak-password':
+ throw new Error('パスワードが脆弱です。より強力なパスワードを設定してください。');
+ default:
+ throw new Error('アカウントの作成に失敗しました。しばらく経ってから再度お試しください。');
+ }
+ }
} 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function signInWithProvider(provider: AuthProvider, withRedirect = true) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const auth = getAuth(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const app = getApp(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -71,7 +84,6 @@ export async function signInWithProvider(provider: AuthProvider, withRedirect = | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Fall back to sign-in by popup method if authDomain is different from location.host | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const cred = await signInWithPopup(auth, provider); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await updateSession(await cred.user.getIdToken()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
invalidate('auth:session'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -80,8 +92,8 @@ export async function signInWithProvider(provider: AuthProvider, withRedirect = | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function signOut() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await updateSession(undefined); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
invalidate('auth:session'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await getAuth().signOut(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
invalidate('auth:session'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
resetRedirectResultHandler(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -96,6 +108,7 @@ async function updateSession(idToken: string | undefined) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
headers: { 'Content-Type': 'application/json' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
body: JSON.stringify({ idToken }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
invalidate('auth:session'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
previousIdToken = idToken; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
<h1>Welcome to SvelteKit</h1> | ||
<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p> | ||
|
||
<p>Home</p> |
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.
エラー情報のログ出力に関するセキュリティ考慮
console.log('error', error);
でエラーオブジェクトをそのままログ出力していますが、これにより機密情報が漏洩する可能性があります。特に本番環境では、エラーメッセージにユーザー情報やシステムの詳細が含まれる場合があります。エラーメッセージを一般化するか、適切なログレベルを使用して詳細情報の露出を防いでください。以下の差分を適用してログ出力を修正してください:
📝 Committable suggestion