ð èªèšŒãµãŒãã¹
èªèšŒãµãŒãã¹ã¯ãã¢ã€ãã³ãã£ãã£ã®ç»é²ããã°ã€ã³ããã°ã¢ãŠããããŒã¯ã³ç®¡çãæäŸããå®å šãªèªèšŒã·ã¹ãã ã§ããJWTããŒã¹ã®ã»ãã¥ãªãã£ããã³ã¯ãããŒå¯Ÿå¿ãåããŠããŸãã
ð ã¯ã€ãã¯ã¹ã¿ãŒãâ
Cookie èªèšŒã䜿çšããå Žåã¯ãcookie-parserïŒããã³ TypeScript åå®çŸ©ïŒãã€ã³ã¹ããŒã«ããŸãã
npm install cookie-parser
npm install -D @types/cookie-parser
import express from 'express';
import cookieParser from 'cookie-parser';
import {services, middlewares, types, drivers} from '@nodeblocks/backend-sdk';
const {withMongo, createGoogleOAuthDriver, createTwitterOAuthDriver, createLineOAuthDriver} = drivers;
const connectToDatabase = withMongo('mongodb://localhost:27017/?authSource=admin', 'dev', 'user', 'password');
express()
// Cookie èªèšŒã䜿çšããã«ãŒãããåã«å¿
èŠ
.use(cookieParser())
.use(
services.authService(
{
...(await connectToDatabase('identities')),
...(await connectToDatabase('refreshtokens')),
...(await connectToDatabase('onetimetokens')),
...(await connectToDatabase('invitations')),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
maxFailedLoginAttempts: 5,
oauth: {allowedRedirectOrigins: ['https://example.com', 'http://localhost:3000']},
authMode: 'cookie',
accessTokenSignOptions: {expiresIn: '15m'},
refreshTokenSignOptions: {expiresIn: '2d'},
onetimeTokenSignOptions: {expiresIn: '5m'},
isMfaEnabled: false, // å€èŠçŽ èªèšŒãæå¹ã«ãã
mfaCodeLength: 6, // MFA ã³ãŒãã®é·ãïŒæ¢å®å€: 6ïŒ
mfaCodeEmailConfig: {
// isMfaEnabled ã true ã®å Žåã«å¿
èŠ
sender: 'noreply@example.com',
emailConfig: {
subject: 'Your MFA Code',
bodyTemplate: 'Your verification code is: ${code}',
},
},
verifyEmailConfig: {
enabled: true,
emailConfig: {
bodyTemplate: 'Hello ${email}',
subject: 'Welcome to our app',
urlTemplate: 'https://example.com/verify-email?token=${token}',
},
sender: 'noreply@example.com',
},
invitation: {
enabled: true,
emailConfig: {
bodyTemplate: '<h1>You\'re invited!</h1><p>Click <a href="${url}">here</a> to accept the invitation.</p>',
subject: "You're invited to join our organization",
urlTemplate: 'https://yourapp.com/invitations/accept?token=${token}&email=${email}',
sender: 'invites@yourapp.com',
},
target: 'invitation',
},
},
{
mailService: {
sendMail: async (mailData: types.MailData) => {
console.log(mailData);
return true;
},
},
googleOAuthDriver: createGoogleOAuthDriver(
process.env.GOOGLE_CLIENT_ID!,
process.env.GOOGLE_CLIENT_SECRET!,
'https://example.com/auth/oauth/google/callback',
),
twitterOAuthDriver: createTwitterOAuthDriver(
process.env.TWITTER_CONSUMER_KEY!,
process.env.TWITTER_CONSUMER_SECRET!,
'https://example.com/auth/oauth/twitter/callback',
process.env.SESSION_SECRET!,
),
lineOAuthDriver: createLineOAuthDriver(
process.env.LINE_CHANNEL_ID!,
process.env.LINE_CHANNEL_SECRET!,
'https://example.com/auth/oauth/line/callback',
),
}
)
)
.use(middlewares.nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));
ðïž ããŒã¿ã¹ãã¢â
| ã³ã¬ã¯ã·ã§ã³ | å¿ é | 説æ |
|---|---|---|
identities | â | èªèšŒãããŒã§äœ¿çšããã¢ã€ãã³ãã£ãã£ã¢ã«ãŠã³ã |
refreshtokens | â | èªèšŒãããŒã§äœ¿çšãããªãã¬ãã·ã¥ããŒã¯ã³ |
invitations | â | æåŸ ã®äœæã»äžèЧã»ååŸã»åé€ã§äœ¿çš |
onetimetokens | â | MFA ããã³ã¯ã³ã¿ã€ã ããŒã¯ã³ã®ãããŒã§äœ¿çš |
ð ãšã³ããã€ã³ãæŠèŠâ
| ã¡ãœãã | ãã¹ | 説æ |
|---|---|---|
| èªèšŒãšã³ããã€ã³ã | ||
| POST | /auth/register | æ°ããã¢ã€ãã³ãã£ãã£ã¢ã«ãŠã³ããç»é² |
| POST | /auth/login | ã¢ã€ãã³ãã£ãã£ãèªèšŒãããŒã¯ã³ãåãåãïŒMFA æå¹æã¯ MFA ããŒã¯ã³ãè¿ãïŒ |
| POST | /auth/mfa/verify | MFA ã³ãŒããæ€èšŒããŠèªèšŒãå®äº |
| POST | /auth/mfa/resend | æ€èšŒçšã® MFA ã³ãŒããåé |
| POST | /auth/ott/login | ã¯ã³ã¿ã€ã ããŒã¯ã³ïŒããžãã¯ãªã³ã¯ïŒã§èªèšŒ |
| POST | /auth/logout | ãã°ã¢ãŠããããŒã¯ã³ãç¡å¹å |
| ã¡ãŒã«ç¢ºèªãšã³ããã€ã³ã | ||
| POST | /auth/:identityId/send-verification-email | ã¢ã€ãã³ãã£ãã£ã«ã¡ãŒã«ç¢ºèªãéä¿¡ |
| POST | /auth/confirm-email | 確èªããŒã¯ã³ã§ã¡ãŒã«ãç¢ºèª |
| ã¡ãŒã«ç®¡çãšã³ããã€ã³ã | ||
| PATCH | /auth/:identityId/change-email | ã¡ãŒã«å€æŽããã»ã¹ãéå§ |
| POST | /auth/confirm-new-email | æ°ããã¡ãŒã«ã¢ãã¬ã¹ãç¢ºèª |
| ãã¹ã¯ãŒã管çãšã³ããã€ã³ã | ||
| POST | /auth/send-reset-password-link-email | ãã¹ã¯ãŒãåèšå®ã¡ãŒã«ãéä¿¡ |
| POST | /auth/reset-password | ãã¹ã¯ãŒãåèšå®ãå®äº |
| PATCH | /auth/:identityId/change-password | ãŠãŒã¶ãŒãã¹ã¯ãŒããå€æŽ |
| ã¢ã«ãŠã³ã管çãšã³ããã€ã³ã | ||
| POST | /auth/activate | ãŠãŒã¶ãŒã¢ã«ãŠã³ããæå¹å |
| POST | /auth/deactivate | ãŠãŒã¶ãŒã¢ã«ãŠã³ããç¡å¹å |
| ããŒã¯ã³ç®¡çãšã³ããã€ã³ã | ||
| POST | /auth/token/check | ã¢ã¯ã»ã¹ããŒã¯ã³ãæ€èšŒ |
| POST | /auth/token/refresh | ãªãã¬ãã·ã¥ããŒã¯ã³ã§ã¢ã¯ã»ã¹ããŒã¯ã³ãæŽæ° |
| DELETE | /auth/:identityId/refresh-tokens | ã¢ã€ãã³ãã£ãã£ã®ãªãã¬ãã·ã¥ããŒã¯ã³ãåé€ |
| æåŸ ãšã³ããã€ã³ã | ||
| POST | /invitations | æåŸ ãæ°èŠäœæ |
| GET | /invitations | æåŸ ãä»»æã®ãã£ã«ã¿ã§äžèЧååŸ |
| GET | /invitations/:invitationId | IDã§æåŸ ãååŸ |
| DELETE | /invitations/:invitationId | æåŸ ãåé€ |
| OAuth ãšã³ããã€ã³ã | ||
| GET | /auth/oauth/google | Google OAuth ãããŒãéå§ |
| GET | /auth/oauth/google/callback | Google OAuth ã³ãŒã«ããã¯ãåŠç |
| GET | /auth/oauth/twitter | Twitter OAuth ãããŒãéå§ |
| GET | /auth/oauth/twitter/callback | Twitter OAuth ã³ãŒã«ããã¯ãåŠç |
| GET | /auth/oauth/line | LINE OAuth ãããŒãéå§ |
| GET | /auth/oauth/line/callback | LINE OAuth ã³ãŒã«ããã¯ãåŠç |
ðïž ãšã³ãã£ãã£ã¹ããŒãâ
èªèšŒãµãŒãã¹ã¯ä»¥äžã®ã¹ããŒãã§ã¢ã€ãã³ãã£ãã£ã管çããŸãïŒ
ã¢ã€ãã³ãã£ãã£ãšã³ãã£ãã£â
{
"id": "string",
"email": "string",
"password": "string",
"attempts": "number",
"locked": "boolean",
"emailVerified": "boolean",
"deactivatedAt": "string | null",
"createdAt": "string",
"updatedAt": "string",
"typeId": "string",
"provider": "string",
"providerId": "string"
}
ãã£ãŒã«ã詳现â
| ãã£ãŒã«ã | å | èªåçæ | å¿ é | 説æ |
|---|---|---|---|---|
id | string | â | â | äžæãªèå¥åïŒUUIDïŒ |
email | string | â | â | ã¢ã€ãã³ãã£ãã£ã®ã¡ãŒã«ã¢ãã¬ã¹ |
password | string | â | â | ããã·ã¥åããããã¹ã¯ãŒã |
attempts | number | â | â | 倱æãããã°ã€ã³è©Šè¡åæ° |
locked | boolean | â | â | ã¢ã«ãŠã³ãã®ããã¯ç¶æ |
emailVerified | boolean | â | â | ã¡ãŒã«ã¢ãã¬ã¹ãç¢ºèªæžã¿ãã©ãã |
deactivatedAt | string ãŸã㯠null | â | â | ã¢ã«ãŠã³ãã®ç¡å¹åæ¥æãã¢ã¯ãã£ããªå Žå㯠null |
createdAt | string | â | â | äœææ¥æ |
updatedAt | string | â | â | æŽæ°æ¥æ |
typeId | string | â | â | ããŒã«èå¥åïŒäŸïŒç®¡çè 㯠"100"ãäžè¬ã¯ "001"ïŒ |
provider | string | â | â ïž | OAuth ãããã€ããŒã®èå¥åïŒäŸïŒgoogleãtwitterãlineïŒ |
providerId | string | â | â ïž | OAuth ã¢ã€ãã³ãã£ãã£çšã®ãããã€ããŒåºæãŠãŒã¶ãŒ ID |
è£è¶³ãã£ãŒã«ã詳现ïŒ
-
attempts: é£ç¶ãã倱æãã°ã€ã³åæ°ã远跡ããŸãããããå€ïŒèšå®å¯èœïŒãè¶ ãããšèªåã§ããã¯ãããŸãã
-
locked: 倱æåæ°ã®è¶ éãŸãã¯ç®¡çæäœã«ããããã¯ãããŠãããã©ãããããã¯äžã¯èªèšŒã§ããŸããã
-
typeId: ã·ã¹ãã å ã®ããŒã«/æš©éã瀺ãèå¥åããµãŒãã¹ããšã«èª¿æŽå¯èœãäŸïŒ
- "100": 管çè ïŒãã«ã¢ã¯ã»ã¹ïŒ
- "001": äžè¬ãŠãŒã¶ãŒïŒåºæ¬æš©éïŒ
- "000": ã²ã¹ãïŒæå°æš©éïŒ
- å¿ èŠã«å¿ããŠã«ã¹ã¿ã ããŒã«ã远å å¯èœ
-
email: OAuth ããŒã¹ã®ã¢ã€ãã³ãã£ãã£ã§ã¯ããã¹ãŠã®ãããã€ããŒãã¡ãŒã«ã¢ãã¬ã¹ãæäŸããããã§ã¯ãããŸããïŒããšãã° TwitterïŒãéåžžã®ç»é²ã§ã¯å¿ é ã§ãã
-
provider: ãã®ã¢ã€ãã³ãã£ãã£ãäœæãã OAuth ãããã€ããŒã瀺ããŸããOAuth ããŒã¹ã®ã¢ã€ãã³ãã£ãã£ã§ã¯å¿ é ã§ããæå®ã§ããå€ã¯
'google'ã'twitter'ã'line'ã§ãã -
providerId: OAuth ãããã€ããŒããŠãŒã¶ãŒã«å²ãåœãŠãäžæã®èå¥åã§ããOAuth ããŒã¹ã®ã¢ã€ãã³ãã£ãã£ã§ã¯å¿ é ã§ããã
providerãšçµã¿åãããŠè€æ°åã®ãã°ã€ã³ã«ãããã¢ã€ãã³ãã£ãã£ã確å®ã«èå¥ããŸãã
æåŸ ãšã³ãã£ãã£â
èªèšŒãµãŒãã¹ã¯ä»¥äžã®ã¹ããŒãã§æåŸ ã管çããŸãïŒ
{
"id": "string",
"email": "string",
"fromIdentityId": "string",
"orgId": "string",
"role": "string",
"status": "string",
"createdAt": "string",
"updatedAt": "string"
}
æåŸ ãã£ãŒã«ã詳现â
| ãã£ãŒã«ã | å | èªåçæ | å¿ é | 説æ |
|---|---|---|---|---|
id | string | â | â | äžæãªèå¥åïŒUUIDïŒ |
email | string | â | â | æåŸ å ã®ã¡ãŒã«ã¢ãã¬ã¹ |
fromIdentityId | string | â | â | æåŸ éä¿¡è ã®ã¢ã€ãã³ãã£ãã£ID |
orgId | string | â | â | æåŸ å ã®çµç¹ID |
role | string | â | â | çµç¹ã§ã®ããŒã« |
status | string | â | â | æåŸ ã®ç¶æ ïŒäŸïŒpending / acceptedïŒ |
createdAt | string | â | â | äœææ¥æ |
updatedAt | string | â | â | æŽæ°æ¥æ |
ð èªèšŒããããŒâ
ä¿è·ããããšã³ããã€ã³ãã§ã¯ã以äžã®ããããŒãå«ããŠãã ããïŒ
Authorization: Bearer <access_token>
x-nb-fingerprint: <device_fingerprint>
â ïž éèŠ: èªå¯æã«ãã£ã³ã¬ãŒããªã³ããæå®ããå ŽåãèªèšŒæžã¿ã®å šãªã¯ãšã¹ãã§
x-nb-fingerprintããããŒãå¿ é ã§ããæ¬ åŠããŠããå Žå㯠401 Unauthorized ãè¿ããŸãã
ð§ APIãšã³ããã€ã³ãâ
1. ã¢ã€ãã³ãã£ãã£ç»é²â
ã¡ãŒã«ã¢ãã¬ã¹ãšãã¹ã¯ãŒãã§æ°èŠã¢ã€ãã³ãã£ãã£ãç»é²ããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/register - ããããŒ:
Content-Type: application/json
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
email | string | â * | ã¢ã€ãã³ãã£ãã£ã®ã¡ãŒã«ã¢ãã¬ã¹ |
password | string | â | ãã¹ã¯ãŒã |
token | string | â * | æåŸ ããŒã¯ã³ |
*email ãŸã㯠token ã®ãããããå¿
é ïŒåææå®äžå¯ïŒã
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒemail+password ãŸã㯠token+password å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'
ããŒã¯ã³æå®ã®ãªã¯ãšã¹ãäŸïŒæ¢åãŠãŒã¶ãŒïŒ:
curl -X POST {{host}}/auth/register \
-H "Content-Type: application/json" \
-d '{
"token": "invitation-token",
"password": "securepassword123"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 201 Created
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ã¡ãŒã«ãæ¢ã«ååšããå Žå:
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json
{
"error": {
"message": "unable to register \"user@example.com\""
}
}
å¿ é ãã£ãŒã«ããæ¬ èœããŠããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'email'",
"request body must have required property 'token'",
"request body must match exactly one schema in oneOf"
]
}
}
2. ãã°ã€ã³â
è³æ Œæ å ±ãèªèšŒããã¢ã¯ã»ã¹ããŒã¯ã³ãšãªãã¬ãã·ã¥ããŒã¯ã³ãåãåããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/login - ããããŒ:
Content-Type: application/json
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
email | string | â | ã¡ãŒã«ã¢ãã¬ã¹ |
password | string | â | ãã¹ã¯ãŒã |
fingerprint | string | â | 端æ«ãã£ã³ã¬ãŒããªã³ã |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
accessToken | string | APIèªèšŒçšã®JWTã¢ã¯ã»ã¹ããŒã¯ã³ |
id | string | ã¢ã€ãã³ãã£ãã£ID |
refreshToken | string | JWTãªãã¬ãã·ã¥ããŒã¯ã³ |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒemail, password å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123",
"fingerprint": "device-fingerprint"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Credentials: true
Set-Cookie: accessToken=...; Path=/
Set-Cookie: refreshToken=...; Path=/
{
"accessToken": "c911c0dd107f8d7e92c0608aa149d041:dee2...",
"id": "0b3839a6-92b4-4044-a13b-ed834a105646",
"refreshToken": "9f0cad0da1ceec15c01de729a2359236:2acc8ee1b57fd971473..."
}
ãšã©ãŒã¬ã¹ãã³ã¹:
è³æ Œæ å ±ãäžæ£ãªå Žå:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "wrong credentials provided"
}
}
3. MFA ã³ãŒãã®æ€èšŒâ
MFA ãæå¹ãªå Žåã«ããã°ã€ã³ã§åãåã£ããã£ã¬ã³ãžããŒã¯ã³ãšã¡ãŒã«ã§éä¿¡ãããã³ãŒããæ€èšŒããŠèªèšŒãå®äºããŸãã
- Method:
POST - Path:
/auth/mfa/verify - èªå¯: äžèŠ
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
token | string | â | ãã°ã€ã³ã§åãåã£ã MFA ãã£ã¬ã³ãžããŒã¯ã³ |
code | string | â | ã¡ãŒã«ã§éä¿¡ããã MFA æ€èšŒã³ãŒã |
ãã¢ã©ãŒã¢ãŒãã§ã¯ accessTokenãrefreshTokenãid ãè¿ããŸããCookie ã¢ãŒãã§ã¯ããŒã¯ã³ã Cookie ã«èšå®ããæ¬æã«ã¯ id ã®ã¿ãè¿ããŸããã³ãŒããããŒã¯ã³ãç¡å¹ãŸãã¯æéåãã®å Žå㯠400 Bad Request ãè¿ããŸãã
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
accessToken | string | API èªèšŒçš JWT ã¢ã¯ã»ã¹ããŒã¯ã³ |
id | string | ã¢ã€ãã³ãã£ãã£ã®äžæèå¥å |
refreshToken | string | æ°ããã¢ã¯ã»ã¹ããŒã¯ã³ååŸçš JWT ãªãã¬ãã·ã¥ããŒã¯ã³ |
curl -X POST {{host}}/auth/mfa/verify \
-H "Content-Type: application/json" \
-d '{"token":"mfa-challenge-token","code":"123456"}'
HTTP/1.1 200 OK
Content-Type: application/json
{"accessToken":"c911c0dd107f8d7e92c0608aa149d041:dee2...","id":"0b3839a6-92b4-4044-a13b-ed834a105646","refreshToken":"9f0cad0da1ceec15c01de729a2359236:2acc8ee1b57fd971473..."}
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Credentials: true
Set-Cookie: accessToken=...; Path=/; HttpOnly; Secure; SameSite=Strict
Set-Cookie: refreshToken=...; Path=/; HttpOnly; Secure; SameSite=Strict
{"id":"0b3839a6-92b4-4044-a13b-ed834a105646"}
{ "error": { "message": "Invalid MFA code" } }
{ "error": { "message": "Invalid or expired MFA token" } }
4. MFA ã³ãŒãã®åéâ
MFA æ€èšŒã³ãŒãããŠãŒã¶ãŒã®ã¡ãŒã«ã¢ãã¬ã¹ãžåéããŸãã
- Method:
POST - Path:
/auth/mfa/resend - èªå¯: äžèŠ
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
token | string | â | ãã°ã€ã³ã§åãåã£ã MFA ãã£ã¬ã³ãžããŒã¯ã³ |
æåæã¯ã以åã®ããŒã¯ã³ãç¡å¹ã«ããæ°ãã token ãè¿ããŸããããŒã¯ã³ãç¡å¹ã»æéåãã®å Žå㯠400ãã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå Žå㯠404 ã§ãã
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
token | string | æ°ãã MFA ãã£ã¬ã³ãžããŒã¯ã³ïŒä»¥åã®ããŒã¯ã³ã¯ç¡å¹ïŒ |
curl -X POST {{host}}/auth/mfa/resend \
-H "Content-Type: application/json" \
-d '{"token":"mfa-challenge-token"}'
HTTP/1.1 200 OK
Content-Type: application/json
{"token":"new-mfa-challenge-token"}
{ "error": { "message": "Invalid or expired MFA token" } }
{ "error": { "message": "Identity not found" } }
5. ã¯ã³ã¿ã€ã ããŒã¯ã³ã«ãããã°ã€ã³â
ããžãã¯ãªã³ã¯ãªã©ã§çºè¡ãããã¯ã³ã¿ã€ã ããŒã¯ã³ã«ãããŠãŒã¶ãŒãèªèšŒããŸãã
- Method:
POST - Path:
/auth/ott/login - èªå¯: äžèŠ
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
token | string | â | èªèšŒçšã¯ã³ã¿ã€ã ããŒã¯ã³ |
æåæã®ã¬ã¹ãã³ã¹ã¯éåžžã®ãã°ã€ã³ãšåãã§ããããŒã¯ã³ããã®æäœã«äœ¿çšã§ããªãå Žå㯠403 Forbidden ãè¿ããŸãã
ã¬ã¹ãã³ã¹ããã£ïŒãã¢ã©ãŒã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
accessToken | string | API èªèšŒçš JWT ã¢ã¯ã»ã¹ããŒã¯ã³ |
id | string | ã¢ã€ãã³ãã£ãã£ã®äžæèå¥å |
refreshToken | string | æ°ããã¢ã¯ã»ã¹ããŒã¯ã³ååŸçš JWT ãªãã¬ãã·ã¥ããŒã¯ã³ |
ã¬ã¹ãã³ã¹ããã£ïŒCookie ã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
id | string | ã¢ã€ãã³ãã£ãã£ã®äžæèå¥å |
curl -X POST {{host}}/auth/ott/login \
-H "Content-Type: application/json" \
-d '{"token":"one-time-login-token"}'
{ "error": { "message": "Token is not valid for one-time login" } }
6. ã¢ã¯ã»ã¹ããŒã¯ã³ã®æŽæ°â
æå¹ãªãªãã¬ãã·ã¥ããŒã¯ã³ããã¢ã¯ã»ã¹ããŒã¯ã³ãæŽæ°ããŸãã
- Method:
POST - Path:
/auth/token/refresh - ããããŒ: å¿
èŠã«å¿ããŠ
x-nb-fingerprint: <device-fingerprint> - èªå¯: äžèŠ
ãã¢ã©ãŒã¢ãŒãã§ã¯æ¬æã« refreshToken ãæå®ããæ°ãã accessToken ãš refreshToken ãåãåããŸããCookie ã¢ãŒãã§ã¯ refreshToken Cookie ã䜿çšããæŽæ°åŸã®ããŒã¯ã³ã Set-Cookie ã§è¿ããŸããç¡å¹ãªãªãã¬ãã·ã¥ããŒã¯ã³ã¯ 401 Unauthorized ã§ãã
ãªã¯ãšã¹ãããã£ïŒãã¢ã©ãŒã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
refreshToken | string | â | æŽæ°ã«äœ¿çšããæå¹ãªãªãã¬ãã·ã¥ããŒã¯ã³ |
ãªã¯ãšã¹ãããã£ïŒCookie ã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
| ããã£ãªã | - | ãªãã¬ãã·ã¥ããŒã¯ã³ã¯ refreshToken Cookie ããèªã¿åã |
ã¬ã¹ãã³ã¹ããã£ïŒãã¢ã©ãŒã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
accessToken | string | æ°ããã¢ã¯ã»ã¹ããŒã¯ã³ |
refreshToken | string | æ°ãããªãã¬ãã·ã¥ããŒã¯ã³ |
ã¬ã¹ãã³ã¹ããã£ïŒCookie ã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | ããŒã¯ã³ã¯ Set-Cookie ã§èšå®ãããæ¬æã¯ç©º |
curl -X POST {{host}}/auth/token/refresh \
-H "Content-Type: application/json" \
-d '{"refreshToken":"<refresh-token>"}'
HTTP/1.1 200 OK
Content-Type: application/json
{"accessToken":"<access-token>","refreshToken":"<refresh-token>"}
{ "error": { "message": "Token is not valid refresh token" } }
7. ãªãã¬ãã·ã¥ããŒã¯ã³ã®åé€â
ç¹å®ã®ã¢ã€ãã³ãã£ãã£ã®ãªãã¬ãã·ã¥ããŒã¯ã³ãåé€ããŸãã管çè ãŸãã¯æ¬äººãå®è¡ã§ããŸãã
- Method:
DELETE - Path:
/auth/:identityId/refresh-tokens - èªå¯: ã¢ã¯ã»ã¹ããŒã¯ã³å¿ é
æåæã¯ 204 No Content ãè¿ããŸãã察象ã®ã¢ã€ãã³ãã£ãã£ããªãå Žå㯠404 Not Found ã§ãã
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ 204 No Content ãè¿ã |
curl -X DELETE {{host}}/auth/<identityId>/refresh-tokens \
-H "Authorization: Bearer <access-token>"
HTTP/1.1 204 No Content
{ "error": { "message": "Identity not found" } }
8. ãã°ã¢ãŠãâ
ãã°ã¢ãŠããããªãã¬ãã·ã¥ããŒã¯ã³ãç¡å¹åããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/logout - ããããŒ:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é
ãªã¯ãšã¹ãããã£ïŒãã¢ã©ãŒã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
refreshToken | string | â | 倱å¹ããããªãã¬ãã·ã¥ããŒã¯ã³ |
ãªã¯ãšã¹ãããã£ïŒCookie ã¢ãŒãïŒ:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
| ããã£ãªã | - | ãªãã¬ãã·ã¥ããŒã¯ã³ã¯ refreshToken Cookie ããèªã¿åã |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: ãã¢ã©ãŒã¢ãŒãã§ã¯ JSON æ¬æã®
refreshTokenãå¿ é ã§ããCookie ã¢ãŒãã§ã¯ç©ºã®æ¬æã¹ããŒãã䜿çšããŸãã - ã«ãŒãããªããŒã·ã§ã³: èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒããŒã¯ã³ïŒå¿ é
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/logout \
-H "Authorization: Bearer <access-token>" \
-H "Content-Type: application/json" \
-d '{"refreshToken":"<refresh-token>"}'
Cookie ã¢ãŒãã®ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/logout \
-H "Cookie: accessToken=<access-token>; refreshToken=<refresh-token>"
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
ãšã©ãŒã¬ã¹ãã³ã¹:
ãªãã¬ãã·ã¥ããŒã¯ã³ã®ç¡å¹åã«å€±æããå Žå:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "failed to delete refresh token"
}
}
9. 確èªã¡ãŒã«éä¿¡â
ã¢ã€ãã³ãã£ãã£ã®ã¡ãŒã«ã¢ãã¬ã¹å®ã«ç¢ºèªçšãªã³ã¯ãéä¿¡ããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/:identityId/send-verification-email - ããããŒ:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ãŸãã¯æ¬äººïŒ
ãã¹ãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
identityId | string | â | ã¢ã€ãã³ãã£ãã£ã®äžæãªID |
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
fingerprint | string | â | ã»ãã¥ãªãã£çšã®ç«¯æ«ãã£ã³ã¬ãŒããªã³ã |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çš
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè ãŸãã¯æ¬äººã§ããããš
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/identity-12345/send-verification-email \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"fingerprint": "device-fingerprint"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ã¡ãŒã«ç¢ºèªæ©èœãç¡å¹ãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "verification email feature not enabled"
}
}
ã¡ãŒã«ãµãŒãã¹ãæªèšå®ã®å Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "verification email feature requires a mail service to be provided"
}
}
ã¡ãŒã«èšå®ãäžè¶³ããŠããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "verifyEmailConfig requires emailConfig with fields bodyTemplate, subject, urlTemplate"
}
}
ã¡ãŒã«éä¿¡ã«å€±æããå Žå:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to send verification email"
}
}
ã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{ "error": { "message": "Identity not found" } }
ã¢ã€ãã³ãã£ãã£ã«ã¡ãŒã«ã¢ãã¬ã¹ããªãå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{ "error": { "message": "Identity has no email address" } }
ã¯ã³ã¿ã€ã ããŒã¯ã³ã®çæã«å€±æããå Žå:
HTTP/1.1 501 Not Implemented
Content-Type: application/json
{ "error": { "message": "failed to generate onetime token" } }
10. ã¡ãŒã«ç¢ºèªâ
確èªããŒã¯ã³ã䜿çšããŠã¡ãŒã«ã¢ãã¬ã¹ã確èªããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/confirm-email - ããããŒ:
Content-Type: application/json
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
token | string | â | ã¡ãŒã«ã«èšèŒã®ç¢ºèªããŒã¯ã³ |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒtoken å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/confirm-email \
-H "Content-Type: application/json" \
-d '{
"token": "jwt-verification-token"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ããŒã¯ã³ãç¡å¹ãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Unable to verify token"
}
}
11. æåŸ ã®äœæâ
ãµãŒãã¹ãžã®åå æåŸ ãæ°èŠäœæããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/invitations - ããããŒ:
Content-Type: application/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ïŒ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
email | string | â | æåŸ å ã®ã¡ãŒã«ã¢ãã¬ã¹ |
fromIdentityId | string | â | æåŸ éä¿¡è ã®ã¢ã€ãã³ãã£ãã£ID |
orgId | string | â | æåŸ å ã®çµç¹ID |
role | string | â | çµç¹å ããŒã« |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
invitationId | string | äœæãããæåŸ ã®äžæID |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒemail, fromIdentityId å¿ é ã»è¿œå ããããã£äžå¯ïŒ
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè æš©éå¿ é
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/invitations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"email": "newuser@example.com",
"fromIdentityId": "392157b1-dc7a-4935-a6f9-a2d333b910ea"
"orgId": "org123",
"role": "member"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 201 Created
Content-Type: application/json
{
"invitationId": "62564a60-e720-4907-bb85-3afaa2729e0d"
}
ãšã©ãŒã¬ã¹ãã³ã¹:
å¿ é ãã£ãŒã«ããæ¬ èœããŠããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'email'"
]
}
}
fromIdentityId ãæ¬ èœããŠããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'fromIdentityId'"
]
}
}
email ã®åœ¢åŒãäžæ£ãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must match format \"email\""
]
}
}
远å ããããã£ãå«ãŸããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"request body must NOT have additional properties"
]
}
}
æåŸ ã®äœæã«å€±æããå Žå:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to create invitation"
}
}
12. æåŸ äžèЧâ
æåŸ ããã£ã«ã¿ãŒã»ããŒãžã³ã°ä»ãã§ååŸããŸãã
ãªã¯ãšã¹ã:
- Method:
GET - Path:
/invitations - ããããŒ:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ïŒ
ã¯ãšãªãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
email | string | â | æåŸ å ã¡ãŒã«ã§ãã£ã«ã¿ãŒ |
fromIdentityId | string | â | æåŸ éä¿¡è IDã§ãã£ã«ã¿ãŒ |
orgId | string | â | çµç¹IDã§ãã£ã«ã¿ãŒ |
role | string | â | ããŒã«ã§ãã£ã«ã¿ãŒ |
page | number | â | ããŒãžçªå· |
limit | number | â | 1ããŒãžä»¶æ° |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
email | string | æåŸ å ã®ã¡ãŒã«ã¢ãã¬ã¹ |
fromIdentityId | string | æåŸ éä¿¡è ã®ã¢ã€ãã³ãã£ãã£ID |
orgId | string | çµç¹ID |
role | string | çµç¹å ããŒã« |
status | string | æåŸ ã®ç¶æ ïŒäŸ: pending/acceptedïŒ |
createdAt | string | äœææ¥æ |
id | string | æåŸ ã®äžæID |
updatedAt | string | æŽæ°æ¥æ |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çš
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè æš©éå¿ é
ãªã¯ãšã¹ãäŸ:
curl -X GET "{{host}}/invitations" \
-H "Authorization: Bearer <access-token>"
æåã¬ã¹ãã³ã¹:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"email": "newuser@example.com",
"fromIdentityId": "392157b1-dc7a-4935-a6f9-a2d333b910ea",
"orgId": "org123",
"role": "member",
"status": "pending",
"createdAt": "2025-07-04T06:29:32.905Z",
"id": "62564a60-e720-4907-bb85-3afaa2729e0d",
"updatedAt": "2025-07-04T06:29:32.905Z"
}
]
空ã¬ã¹ãã³ã¹:
HTTP/1.1 200 OK
Content-Type: application/json
[]
13. æåŸ ã®ååŸïŒIDæå®ïŒâ
äžæIDã§ç¹å®ã®æåŸ ãååŸããŸãã
ãªã¯ãšã¹ã:
- Method:
GET - Path:
/invitations/:invitationId - ããããŒ:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ïŒ
ãã¹ãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
invitationId | string | â | æåŸ ã®äžæID |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çš
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè æš©éå¿ é
ãªã¯ãšã¹ãäŸ:
curl -X GET {{host}}/invitations/62564a60-e720-4907-bb85-3afaa2729e0d \
-H "Authorization: Bearer <access-token>"
æåã¬ã¹ãã³ã¹:
HTTP/1.1 200 OK
Content-Type: application/json
{
"email": "newuser@example.com",
"fromIdentityId": "392157b1-dc7a-4935-a6f9-a2d333b910ea",
"orgId": "org123",
"role": "member",
"status": "pending",
"createdAt": "2025-07-04T06:29:32.905Z",
"id": "62564a60-e720-4907-bb85-3afaa2729e0d",
"updatedAt": "2025-07-04T06:29:32.905Z"
}
ãšã©ãŒã¬ã¹ãã³ã¹:
æåŸ ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Invitation not found"
}
}
14. æåŸ ã®åé€â
äžæIDã§ç¹å®ã®æåŸ ãåé€ããŸãã
ãªã¯ãšã¹ã:
- Method:
DELETE - Path:
/invitations/:invitationId - ããããŒ:
Authorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ïŒ
ãã¹ãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
invitationId | string | â | æåŸ ã®äžæID |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çš
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè æš©éå¿ é
ãªã¯ãšã¹ãäŸ:
curl -X DELETE {{host}}/invitations/62564a60-e720-4907-bb85-3afaa2729e0d \
-H "Authorization: Bearer <access-token>"
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 OK
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
æåŸ ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Invitation not found"
}
}
15. ã¡ãŒã«å€æŽã®éå§â
æ°ããã¡ãŒã«ã¢ãã¬ã¹ã«ç¢ºèªã¡ãŒã«ãéä¿¡ããã¡ãŒã«å€æŽããã»ã¹ãéå§ããŸãã
ãªã¯ãšã¹ã:
- Method:
PATCH - Path:
/auth/:identityId/change-email - ããããŒ:
Content-Type: application/json
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ãŸãã¯æ¬äººïŒ
ãã¹ãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
identityId | string | â | ã¢ã€ãã³ãã£ãã£ã®äžæID |
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
email | string | â | æ°ããã¡ãŒã«ã¢ãã¬ã¹ |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒemail å¿ é ã»ã¡ãŒã«åœ¢åŒïŒ
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè ãŸãã¯æ¬äººã§ããããš
ãªã¯ãšã¹ãäŸ:
curl -X PATCH {{host}}/auth/identity-12345/change-email \
-H "Content-Type: application/json" \
-d '{
"email": "newemail@example.com"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ã¡ãŒã«ãæ¢ã«ååšããå Žå:
HTTP/1.1 409 Conflict
Content-Type: application/json
{
"error": {
"message": "Email already exists"
}
}
ã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Identity not found"
}
}
16. æ°ããã¡ãŒã«ã®ç¢ºèªâ
ã¯ã³ã¿ã€ã 確èªããŒã¯ã³ã§æ°ããã¡ãŒã«ã¢ãã¬ã¹ã確å®ããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/confirm-new-email - ããããŒ:
Content-Type: application/json
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
token | string | â | ã¡ãŒã«ã®ç¢ºèªããŒã¯ã³ |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒtoken å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/confirm-new-email \
-H "Content-Type: application/json" \
-d '{
"token": "jwt-verification-token"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ããŒã¯ã³ãç¡å¹ãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Invalid token"
}
}
17. ãã¹ã¯ãŒãåèšå®ãªã³ã¯éä¿¡â
ã¡ãŒã«ã¢ãã¬ã¹ã«åºã¥ããŠãã¹ã¯ãŒãåèšå®ãªã³ã¯ãéä¿¡ããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/send-reset-password-link-email - ããããŒ:
Content-Type: application/json
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
email | string | â | ãã¹ã¯ãŒãåèšå®çšã®ã¡ãŒã«ã¢ãã¬ã¹ |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒemail å¿ é ã»ã¡ãŒã«åœ¢åŒïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/send-reset-password-link-email \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ã¡ãŒã«ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Email not found"
}
}
18. ãã¹ã¯ãŒãåèšå®ã®å®äºâ
ããŒã¯ã³ãæ€èšŒããæ°ãããã¹ã¯ãŒãã«æŽæ°ããŠåèšå®ãå®äºããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/reset-password - ããããŒ:
Content-Type: application/jsonAuthorization: Bearer <one-time-token>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒã¯ã³ã¿ã€ã ããŒã¯ã³ïŒ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
password | string | â | æ°ãããã¹ã¯ãŒãïŒ8ã24æåãè±å°æåãšæ°åãå«ãïŒ |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒpassword å¿ é ã»ã»ãã¥ãªãã£èŠä»¶ãæºããïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/reset-password \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <one-time-token>" \
-d '{
"password": "newSecurePassword123"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ããŒã¯ã³ãç¡å¹ãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Invalid token"
}
}
ãã¹ã¯ãŒããèŠä»¶ãæºãããªãå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"password must match pattern \"^(?=.*[a-z])(?=.*\\d)[a-zA-Z0-9?/_-]{8,24}$\""
]
}
}
19. ãã¹ã¯ãŒã倿Žâ
PATCH /auth/:identityId/change-password ã§ãã¹ã¯ãŒãã倿ŽããŸãã
ãªã¯ãšã¹ã:
- Method:
PATCH - Path:
/auth/:identityId/change-password - ããããŒ:
Content-Type: application/jsonAuthorization: Bearer <token>x-nb-fingerprint: <device-fingerprint>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é
ãã¹ãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
identityId | string | â | ã¢ã€ãã³ãã£ãã£ã®äžæID |
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
password | string | â | çŸåšã®ãã¹ã¯ãŒãïŒç¢ºèªçšïŒ |
newPassword | string | â | æ°ãããã¹ã¯ãŒãïŒ8ã24æåãè±å°æåãšæ°åãå«ãïŒ |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒpassword, newPassword å¿ é ã»èŠä»¶ãæºããïŒ
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè ãŸãã¯æ¬äººã§ããããš
ãªã¯ãšã¹ãäŸ:
curl -X PATCH {{host}}/auth/identity-12345/change-password \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"password": "oldPassword123",
"newPassword": "newSecurePassword123"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
çŸåšã®ãã¹ã¯ãŒããæ£ãããªãå Žå:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "Current password is incorrect"
}
}
æ°ãããã¹ã¯ãŒããèŠä»¶ãæºãããªãå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"newPassword must match pattern \"^(?=.*[a-z])(?=.*\\d)[a-zA-Z0-9?/_-]{8,24}$\""
]
}
}
20. ã¢ã«ãŠã³ãæå¹åâ
POST /auth/activate ã§ã¢ã«ãŠã³ããæå¹åããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/activate - ããããŒ:
Content-Type: application/jsonAuthorization: Bearer <token>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ïŒ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
identityId | string | â | æå¹å察象ã®ã¢ã€ãã³ãã£ãã£ID |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒidentityId å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè æš©éå¿ é
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/activate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"identityId": "identity-12345"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Identity not found"
}
}
ã¡ãŒã«ãæªç¢ºèªã®å Žå:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": {
"message": "Email must be verified before activation"
}
}
21. ã¢ã«ãŠã³ãç¡å¹åâ
POST /auth/deactivate ã§ã¢ã€ãã³ãã£ãã£ãç¡å¹åããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/deactivate - ããããŒ:
Content-Type: application/jsonAuthorization: Bearer <token>
- èªå¯: ãã¢ã©ãŒããŒã¯ã³å¿ é ïŒç®¡çè ãŸãã¯æ¬äººïŒ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
identityId | string | â | ç¡å¹å察象ã®ã¢ã€ãã³ãã£ãã£ID |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒidentityId å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³:
- èªèšŒæžã¿ãªã¯ãšã¹ãïŒãã¢ã©ãŒïŒå¿ é
- 管çè ãŸãã¯æ¬äººã§ããããš
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/deactivate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"identityId": "identity-12345"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 204 No Content
Content-Type: application/json
ãšã©ãŒã¬ã¹ãã³ã¹:
ã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Identity not found"
}
}
ã¡ãŒã«ãæªç¢ºèªã®å Žå:
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"error": {
"message": "Email must be verified before deactivation"
}
}
ããŒã¯ã³ãæ¬ èœããŠããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Missing token header"
}
}
ã¡ãŒã«éä¿¡ã«å€±æããå Žå:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to send email"
}
}
22. ããŒã¯ã³æ€èšŒâ
ã¢ã¯ã»ã¹ããŒã¯ã³ãæ€èšŒãããã®ç¶æ ãè¿ããŸãã
ãªã¯ãšã¹ã:
- Method:
POST - Path:
/auth/token/check - ããããŒ:
Content-Type: application/json
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
token | string | â | æ€èšŒå¯Ÿè±¡ã®ããŒã¯ã³ |
target | string | â | ä»»æã®æ€èšŒã³ã³ããã¹ã |
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
identityId | string | æå¹ãªå Žåã®ã¢ã€ãã³ãã£ãã£ID |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: èªåé©çšïŒtoken å¿ é ïŒ
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -X POST {{host}}/auth/token/check \
-H "Content-Type: application/json" \
-d '{
"token": "jwt-token-to-validate",
"target": "optional-target-context"
}'
æåã¬ã¹ãã³ã¹:
HTTP/1.1 200 OK
Content-Type: application/json
{
"identityId": "811ff0a3-a26f-447b-b68a-dd83ea4000b9"
}
ãšã©ãŒã¬ã¹ãã³ã¹:
ããŒã¯ã³ãç¡å¹ãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Unable to verify token"
}
}
23. Google OAuth éå§â
Google ã®èªå¯ããŒãžã«ãªãã€ã¬ã¯ãã㊠OAuth èªèšŒãããŒãéå§ããŸãããã°ã€ã³/ãµã€ã³ã¢ããã®äž¡æ¹ã«å©çšã§ããæªç»é²ãŠãŒã¶ãŒã¯èªåäœæãæ¢åãŠãŒã¶ãŒã¯èªèšŒãããŸãã
ãªãã€ã¬ã¯ãæ€èšŒ: ãããã€ã㌠state ã®æºåããã©ã€ããŒã®åŒã³åºãåã«ããã³ãã©ãŒã¯ redirectUrl ã oauth.allowedRedirectOrigins ã«å¯ŸããŠæ€èšŒããŸããäžæ£ãª URL ãçžå¯Ÿ URL 㯠400ïŒInvalid redirect URLïŒãèš±å¯ãããŠããªããªãªãžã³ã¯ 400ïŒRedirect URL origin '<origin>' is not allowedïŒãè¿ãããããã€ããŒãžã®ãªã¯ãšã¹ãã忢ããŸãããªãªãžã³ãæªèšå®ãŸãã¯ç©ºã®å Žå㯠AuthenticationUnexpectedErrorïŒNo origins to check againstïŒãè¿ããéå§ã«ãŒãã 500 ã«å¯Ÿå¿ä»ããŸããã³ãŒã«ããã¯ã¯ãããŒã¯ã³ã®ä¿ååã«å®å
ãåæ€èšŒããŸãã
ãªã¯ãšã¹ã:
- Method:
GET - Path:
/auth/oauth/google - ããããŒ: ãªã
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
| ããã£ãªã | - | ãªããèšå®ã¯ã¯ãšãªãã©ã¡ãŒã¿ã§æå® |
ã¯ãšãªãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
fp | string | â | 端æ«ãã£ã³ã¬ãŒããªã³ã |
purpose | string | â | ãããŒç®çïŒoauth-login ãŸã㯠oauth-signup |
redirectUrl | string | â | ããã³ããšã³ãã®çµ¶å¯Ÿ URLãoauth.allowedRedirectOrigins ã§èš±å¯ããããªãªãžã³ãå¿
èŠã§ããéå§æãšã³ãŒã«ããã¯æã«ãªãªãžã³ãæ€èšŒããŸãã |
typeId | string | â | ã¢ã€ãã³ãã£ãã£çš®å¥IDïŒãµã€ã³ã¢ããæã«å¿ èŠïŒ |
ã¬ã¹ãã³ã¹:
- ã¹ããŒã¿ã¹:
302 Found - ããããŒ: Google OAuth URL ãå«ã
Location
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ãªã¯ãšã¹ãäŸ:
# OAuth Login
curl -v "{{host}}/auth/oauth/google?fp=device-fingerprint&purpose=oauth-login&redirectUrl=http://localhost:3000/oauth/callback"
# OAuth Signup
curl -v "{{host}}/auth/oauth/google?fp=device-fingerprint&purpose=oauth-signup&redirectUrl=http://localhost:3000/oauth/callback&typeId=001"
æåã¬ã¹ãã³ã¹:
HTTP/1.1 302 Found
Location: https://accounts.google.com/o/oauth2/v2/auth?prompt=consent&response_type=code&redirect_uri=...&scope=email%20profile&state=...&client_id=...
ãšã©ãŒã¬ã¹ãã³ã¹:
å¿ é ãã©ã¡ãŒã¿ãäžè¶³ããŠããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"query parameter 'fp' is required",
"query parameter 'purpose' is required",
"query parameter 'redirectUrl' is required"
]
}
}
purpose ãäžæ£ãªå€ã®å Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": [
"query parameter 'purpose' must be equal to one of the allowed values"
]
}
}
24. Google OAuth ã³ãŒã«ããã¯â
Google OAuth ã³ãŒã«ããã¯ãåŠçããŸãããããã€ããŒã®ã³ãŒã«ããã¯ãåŠçã㊠state ãååŸããåŸãstate ã® redirectUrl ã configuration.oauth.allowedRedirectOrigins ã«å¯ŸããŠæ€èšŒããŸããæ€èšŒã«æåãããšãã¢ã€ãã³ãã£ãã£ãæ€çŽ¢ãŸãã¯äœæããã¯ã³ã¿ã€ã ããŒã¯ã³ãçæã»ä¿åããŠãèš±å¯ãããå®å
ã« onetimeToken ã远å ããŠãªãã€ã¬ã¯ãããŸãããªãã€ã¬ã¯ããã«ããŒã¯è¿œå ã®ãã³ãŒããè¡ãããæå® URL ã®ããŒã»ã³ããšã³ã³ãŒãã£ã³ã°ãä¿æããŸããgenerateRedirectURL ãåç
§ããŠãã ããã
- ãã³ãã©ãŒã«ããæ€èšŒ: ãªãã€ã¬ã¯ãå
ã¯çµ¶å¯Ÿ URL ã§ããããã®ãªãªãžã³ã空ã§ãªã
oauth.allowedRedirectOriginsèš±å¯ãªã¹ããšäžèŽããå¿ èŠããããŸããã³ãŒã«ããã¯ã¯ããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçåŸãã¢ã€ãã³ãã£ãã£ã®æ€æ»ãšããŒã¯ã³ã®çæã»ä¿åããåã«ãéå§æã®ãªãªãžã³æ€èšŒãå床è¡ããŸãã
ãªãã€ã¬ã¯ãæ€èšŒãšã©ãŒïŒGoogleãLINEãTwitter å ±éïŒ:
| ã¹ããŒã¿ã¹ | ãšã©ãŒã¯ã©ã¹ | ã¡ãã»ãŒãž / æ¡ä»¶ |
|---|---|---|
400 | AuthenticationInvalidInputError | Invalid redirect URL â çžå¯Ÿ URL ãªã©ãURL ã®è§£æã«å€±æããå Žåã |
400 | AuthenticationInvalidInputError | Redirect URL origin '<origin>' is not allowed â ãªãªãžã³ãèš±å¯ãªã¹ããšäžèŽããªãå Žåã |
500 | AuthenticationUnexpectedError | No origins to check against â oauth.allowedRedirectOrigins ãæªèšå®ãŸãã¯ç©ºã®å Žåã |
ãããã®ãšã©ãŒã¯ãSDK ã«ããã¢ã€ãã³ãã£ãã£ã®æ€æ»ã»æ€çŽ¢ã»äœæãã¯ã³ã¿ã€ã ããŒã¯ã³ã®çæã»ä¿åãæçµãªãã€ã¬ã¯ãããåã«åŠçã忢ããŸãããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçã¯ããã®æ€èšŒããå
ã«è¡ãããŸãããªãªãžã³ãèš±å¯ãããŠããã°ãäžèšã® 302 ã¬ã¹ãã³ã¹ãžé²ã¿ãŸããç
§åèŠå㯠validateURL ãåç
§ããŠãã ããã
ãªã¯ãšã¹ã:
- Method:
GET - Path:
/auth/oauth/google/callback - ããããŒ: ãªã
- èªå¯: äžèŠ
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
| ããã£ãªã | - | ãªããåŠçã¯ã¯ãšãªãã©ã¡ãŒã¿ã§è¡ã |
ã¯ãšãªãã©ã¡ãŒã¿:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
code | string | â | Google ããã®ã¯ã³ã¿ã€ã èªå¯ã³ãŒãïŒPassport.js ã«ãã亀æïŒ |
state | string | â | ãããŒæèãå«ã眲åä»ãJWTïŒpurpose, redirectUrl, typeId, fingerprint, userAgentïŒ |
ã¬ã¹ãã³ã¹:
- ã¹ããŒã¿ã¹:
302 FoundïŒæçµé·ç§»å ãžãªãã€ã¬ã¯ãïŒ - ããããŒ: æçµãªãã€ã¬ã¯ãURLã®
Location
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ããã£ãªã | - | æåæã¯ã¬ã¹ãã³ã¹ããã£ãªã |
ããªããŒã·ã§ã³:
- ã¹ããŒãæ€èšŒ: ãªã
- ã«ãŒãããªããŒã·ã§ã³: ãªã
ãªã¯ãšã¹ãäŸ:
curl -v "{{host}}/auth/oauth/google/callback?code=AUTH_CODE&state=STATE_TOKEN"
æåã¬ã¹ãã³ã¹:
HTTP/1.1 302 Found
Location: http://localhost:3000/oauth/callback?onetimeToken=ONETIME_TOKEN
ãšã©ãŒã¬ã¹ãã³ã¹:
OAuth state ãç¡å¹ãŸãã¯æéåãã®å Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Invalid onetime token"
}
}
ãµã€ã³ã¢ããã« typeId ãå¿ èŠãªå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "typeId is required"
}
}
ã¢ã€ãã³ãã£ãã£äœæã«å€±æããå Žå:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to create identity"
}
}
該åœããã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå Žå:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "No identity found for the given email."
}
}
DBæäœã«å€±æããå Žå:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Error finding or creating identity"
}
}
25. Twitter OAuth éå§â
Twitter OAuth ãéå§ããã«ã¯ GET /auth/oauth/twitter ã䜿çšããŸããpurpose ãš redirectUrl ãæå®ãããµã€ã³ã¢ããæã«ã¯ typeId ã远å ããŸããTwitter ã®éå§ãããŒã«ã¯ fp ã¯äžèŠã§ãã
ãªãã€ã¬ã¯ãæ€èšŒ: ãããã€ã㌠state ã®æºåããã©ã€ããŒã®åŒã³åºãåã«ããã³ãã©ãŒã¯ redirectUrl ã oauth.allowedRedirectOrigins ã«å¯ŸããŠæ€èšŒããŸããäžæ£ãª URL ãçžå¯Ÿ URL 㯠400ïŒInvalid redirect URLïŒãèš±å¯ãããŠããªããªãªãžã³ã¯ 400ïŒRedirect URL origin '<origin>' is not allowedïŒãè¿ãããããã€ããŒãžã®ãªã¯ãšã¹ãã忢ããŸãããªãªãžã³ãæªèšå®ãŸãã¯ç©ºã®å Žå㯠AuthenticationUnexpectedErrorïŒNo origins to check againstïŒãè¿ããéå§ã«ãŒãã 500 ã«å¯Ÿå¿ä»ããŸããã³ãŒã«ããã¯ã¯ãããŒã¯ã³ã®ä¿ååã«å®å
ãåæ€èšŒããŸãã
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
| ãªã¯ãšã¹ãããã£ãªã | - | - | ããã£ã¯äžèŠã§ããèšå®ã«ã¯ã¯ãšãªãã©ã¡ãŒã¿ã䜿çšããŸãã |
| ã¯ãšãªãã©ã¡ãŒã¿ | å | å¿ é | 説æ |
|---|---|---|---|
purpose | string | â | OAuth ã®ç®ç: oauth-login ãŸã㯠oauth-signup |
redirectUrl | string | â | ããã³ããšã³ãã®çµ¶å¯Ÿ URLãoauth.allowedRedirectOrigins ã§èš±å¯ããããªãªãžã³ãå¿
èŠã§ããéå§æãšã³ãŒã«ããã¯æã«ãªãªãžã³ãæ€èšŒããŸãã |
typeId | string | â | ã¢ã€ãã³ãã£ãã£çš®å¥ IDïŒãµã€ã³ã¢ããæã¯å¿ é ïŒ |
æåæã¯ 302 Found ãš Twitter OAuth URL ãå«ã Location ããããŒãè¿ããæ¬æã¯ãããŸããã
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ã¬ã¹ãã³ã¹ããã£ãªã | - | OAuth éå§ãšã³ããã€ã³ãã¯æåæã«ã¬ã¹ãã³ã¹ããã£ãè¿ããŸããã |
# OAuth Login
curl -v "{{host}}/auth/oauth/twitter?purpose=oauth-login&redirectUrl=http://localhost:3000/oauth/callback"
# OAuth Signup
curl -v "{{host}}/auth/oauth/twitter?purpose=oauth-signup&redirectUrl=http://localhost:3000/oauth/callback&typeId=001"
HTTP/1.1 302 Found
Location: https://api.twitter.com/oauth/authenticate?oauth_token=...
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Validation Error",
"data": ["query parameter 'purpose' is required", "query parameter 'redirectUrl' is required"]
}
}
purpose=oauth-login ãæå®ãããšãæ¢åã¢ã€ãã³ãã£ãã£çšã® Twitter ãã°ã€ã³ãããŒãéå§ããŸããpurpose=oauth-signup ãš typeId ãæå®ãããšãæ°èŠã¢ã€ãã³ãã£ãã£çšã®ãµã€ã³ã¢ãããããŒãéå§ããŸãã
26. Twitter OAuth ã³ãŒã«ããã¯â
Twitter OAuth ã³ãŒã«ããã¯ãåŠçããŸãããããã€ããŒã®ã³ãŒã«ããã¯ãåŠçã㊠state ãååŸããåŸãstate ã® redirectUrl ã configuration.oauth.allowedRedirectOrigins ã«å¯ŸããŠæ€èšŒããŸããæ€èšŒã«æåãããšãã¢ã€ãã³ãã£ãã£ãæ€çŽ¢ãŸãã¯äœæããã¯ã³ã¿ã€ã ããŒã¯ã³ãçæã»ä¿åããŠãèš±å¯ãããå®å
ã« onetimeToken ã远å ããŠãªãã€ã¬ã¯ãããŸãããªãã€ã¬ã¯ããã«ããŒã¯è¿œå ã®ãã³ãŒããè¡ãããæå® URL ã®ããŒã»ã³ããšã³ã³ãŒãã£ã³ã°ãä¿æããŸããgenerateRedirectURL ãåç
§ããŠãã ããã
- ãã³ãã©ãŒã«ããæ€èšŒ: ãªãã€ã¬ã¯ãå
ã¯çµ¶å¯Ÿ URL ã§ããããã®ãªãªãžã³ã空ã§ãªã
oauth.allowedRedirectOriginsèš±å¯ãªã¹ããšäžèŽããå¿ èŠããããŸããã³ãŒã«ããã¯ã¯ããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçåŸãã¢ã€ãã³ãã£ãã£ã®æ€æ»ãšããŒã¯ã³ã®çæã»ä¿åããåã«ãéå§æã®ãªãªãžã³æ€èšŒãå床è¡ããŸãã
ãªãã€ã¬ã¯ãæ€èšŒãšã©ãŒïŒGoogleãLINEãTwitter å ±éïŒ:
| ã¹ããŒã¿ã¹ | ãšã©ãŒã¯ã©ã¹ | ã¡ãã»ãŒãž / æ¡ä»¶ |
|---|---|---|
400 | AuthenticationInvalidInputError | Invalid redirect URL â çžå¯Ÿ URL ãªã©ãURL ã®è§£æã«å€±æããå Žåã |
400 | AuthenticationInvalidInputError | Redirect URL origin '<origin>' is not allowed â ãªãªãžã³ãèš±å¯ãªã¹ããšäžèŽããªãå Žåã |
500 | AuthenticationUnexpectedError | No origins to check against â oauth.allowedRedirectOrigins ãæªèšå®ãŸãã¯ç©ºã®å Žåã |
ãããã®ãšã©ãŒã¯ãSDK ã«ããã¢ã€ãã³ãã£ãã£ã®æ€æ»ã»æ€çŽ¢ã»äœæãã¯ã³ã¿ã€ã ããŒã¯ã³ã®çæã»ä¿åãæçµãªãã€ã¬ã¯ãããåã«åŠçã忢ããŸãããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçã¯ããã®æ€èšŒããå
ã«è¡ãããŸãããªãªãžã³ãèš±å¯ãããŠããã°ãäžèšã® 302 ã¬ã¹ãã³ã¹ãžé²ã¿ãŸããç
§åèŠå㯠validateURL ãåç
§ããŠãã ããã
ãªã¯ãšã¹ãããã£:
| ãã£ãŒã«ã | å | å¿ é | 説æ |
|---|---|---|---|
| ãªã¯ãšã¹ãããã£ãªã | - | - | ããã£ã¯äžèŠã§ããOAuth ã³ãŒã«ããã¯åŠçã«ã¯ã¯ãšãªãã©ã¡ãŒã¿ã䜿çšããŸãã |
| ã¯ãšãªãã©ã¡ãŒã¿ | å | å¿ é | 説æ |
|---|---|---|---|
oauth_token | string | â | Twitter ã® OAuth ããŒã¯ã³ |
oauth_verifier | string | â | Twitter ã® OAuth æ€èšŒå |
ã¬ã¹ãã³ã¹: 302 FoundïŒæçµçãªå®å
ãžãªãã€ã¬ã¯ãïŒãšãæçµãªãã€ã¬ã¯ã URL ãå«ã Location ããããŒãè¿ããŸãã
ã¬ã¹ãã³ã¹ããã£:
| ãã£ãŒã«ã | å | 説æ |
|---|---|---|
| ã¬ã¹ãã³ã¹ããã£ãªã | - | OAuth ã³ãŒã«ããã¯ãšã³ããã€ã³ãã¯æåæã«ã¬ã¹ãã³ã¹ããã£ãè¿ããŸããã |
ããªããŒã·ã§ã³: ã¹ããŒãæ€èšŒããã³ã«ãŒãããªããŒã¿ãŒã¯ãããŸããã
curl -v "{{host}}/auth/oauth/twitter/callback?oauth_token=OAUTH_TOKEN&oauth_verifier=OAUTH_VERIFIER"
HTTP/1.1 302 Found
Location: http://localhost:3000/oauth/callback?onetimeToken=ONETIME_TOKEN
{ "error": { "message": "Invalid OAuth token" } }
ãµã€ã³ã¢ããã§çš®å¥ ID ããªãå Žå㯠"typeId is required"ãã¢ã€ãã³ãã£ãã£ã®äœæã«å€±æããå Žå㯠"Failed to create identity" ãè¿ãããŸãã
{ "error": { "message": "No identity found for the given twitter account." } }
27. LINE OAuth éå§â
LINE OAuth ãéå§ããã«ã¯ GET /auth/oauth/line ã䜿çšããŸããfpãpurposeãredirectUrl ãæå®ãããµã€ã³ã¢ããæã«ã¯ typeId ã远å ããŸãã
ãªãã€ã¬ã¯ãæ€èšŒ: ãããã€ã㌠state ã®æºåããã©ã€ããŒã®åŒã³åºãåã«ããã³ãã©ãŒã¯ redirectUrl ã oauth.allowedRedirectOrigins ã«å¯ŸããŠæ€èšŒããŸããäžæ£ãª URL ãçžå¯Ÿ URL 㯠400ïŒInvalid redirect URLïŒãèš±å¯ãããŠããªããªãªãžã³ã¯ 400ïŒRedirect URL origin '<origin>' is not allowedïŒãè¿ãããããã€ããŒãžã®ãªã¯ãšã¹ãã忢ããŸãããªãªãžã³ãæªèšå®ãŸãã¯ç©ºã®å Žå㯠AuthenticationUnexpectedErrorïŒNo origins to check againstïŒãè¿ããéå§ã«ãŒãã 500 ã«å¯Ÿå¿ä»ããŸããã³ãŒã«ããã¯ã¯ãããŒã¯ã³ã®ä¿ååã«å®å
ãåæ€èšŒããŸãã
| ã¯ãšãªãã©ã¡ãŒã¿ | å | å¿ é | 説æ |
|---|---|---|---|
fp | string | â | ã»ãã¥ãªãã£çšããã€ã¹ãã£ã³ã¬ãŒããªã³ã |
purpose | string | â | OAuth ã®ç®ç: oauth-login ãŸã㯠oauth-signup |
redirectUrl | string | â | ããã³ããšã³ãã®çµ¶å¯Ÿ URLãoauth.allowedRedirectOrigins ã§èš±å¯ããããªãªãžã³ãå¿
èŠã§ããéå§æãšã³ãŒã«ããã¯æã«ãªãªãžã³ãæ€èšŒããŸãã |
typeId | string | â | æ°èŠã¢ã€ãã³ãã£ãã£ã®çš®å¥ IDïŒãµã€ã³ã¢ããæã¯å¿ é ïŒ |
èªå¯ã¯äžèŠã§ããæåæã¯ LINE ã®èªå¯ããŒãžãžç§»åãã 302 Found ãš Location ããããŒãè¿ããæ¬æã¯ãããŸããã
curl -X GET "{{host}}/auth/oauth/line?fp=device-fingerprint&purpose=oauth-signup&redirectUrl=https://example.com/auth/callback&typeId=regular"
HTTP/1.1 302 Found
Location: https://access.line.me/oauth2/v2.1/authorize?...
{ "error": { "message": "redirectUrl is required" } }
{ "error": { "message": "typeId is required" } }
28. LINE OAuth ã³ãŒã«ããã¯â
LINE OAuth ã³ãŒã«ããã¯ãåŠçããŸãããããã€ããŒã®ã³ãŒã«ããã¯ãåŠçã㊠state ãååŸããåŸãstate ã® redirectUrl ã configuration.oauth.allowedRedirectOrigins ã«å¯ŸããŠæ€èšŒããŸããæ€èšŒã«æåãããšãã¢ã€ãã³ãã£ãã£ãæ€çŽ¢ãŸãã¯äœæããã¯ã³ã¿ã€ã ããŒã¯ã³ãçæã»ä¿åããŠãèš±å¯ãããå®å
ã« onetimeToken ã远å ããŠãªãã€ã¬ã¯ãããŸãããªãã€ã¬ã¯ããã«ããŒã¯è¿œå ã®ãã³ãŒããè¡ãããæå® URL ã®ããŒã»ã³ããšã³ã³ãŒãã£ã³ã°ãä¿æããŸããgenerateRedirectURL ãåç
§ããŠãã ããã
- ãã³ãã©ãŒã«ããæ€èšŒ: ãªãã€ã¬ã¯ãå
ã¯çµ¶å¯Ÿ URL ã§ããããã®ãªãªãžã³ã空ã§ãªã
oauth.allowedRedirectOriginsèš±å¯ãªã¹ããšäžèŽããå¿ èŠããããŸããã³ãŒã«ããã¯ã¯ããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçåŸãã¢ã€ãã³ãã£ãã£ã®æ€æ»ãšããŒã¯ã³ã®çæã»ä¿åããåã«ãéå§æã®ãªãªãžã³æ€èšŒãå床è¡ããŸãã
ãªãã€ã¬ã¯ãæ€èšŒãšã©ãŒïŒGoogleãLINEãTwitter å ±éïŒ:
| ã¹ããŒã¿ã¹ | ãšã©ãŒã¯ã©ã¹ | ã¡ãã»ãŒãž / æ¡ä»¶ |
|---|---|---|
400 | AuthenticationInvalidInputError | Invalid redirect URL â çžå¯Ÿ URL ãªã©ãURL ã®è§£æã«å€±æããå Žåã |
400 | AuthenticationInvalidInputError | Redirect URL origin '<origin>' is not allowed â ãªãªãžã³ãèš±å¯ãªã¹ããšäžèŽããªãå Žåã |
500 | AuthenticationUnexpectedError | No origins to check against â oauth.allowedRedirectOrigins ãæªèšå®ãŸãã¯ç©ºã®å Žåã |
ãããã®ãšã©ãŒã¯ãSDK ã«ããã¢ã€ãã³ãã£ãã£ã®æ€æ»ã»æ€çŽ¢ã»äœæãã¯ã³ã¿ã€ã ããŒã¯ã³ã®çæã»ä¿åãæçµãªãã€ã¬ã¯ãããåã«åŠçã忢ããŸãããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçã¯ããã®æ€èšŒããå
ã«è¡ãããŸãããªãªãžã³ãèš±å¯ãããŠããã°ãäžèšã® 302 ã¬ã¹ãã³ã¹ãžé²ã¿ãŸããç
§åèŠå㯠validateURL ãåç
§ããŠãã ããã
| ã¯ãšãªãã©ã¡ãŒã¿ | å | å¿ é | 説æ |
|---|---|---|---|
code | string | â | LINE ããã®èªå¯ã³ãŒã |
state | string | â | CSRF ä¿è·çšã® state ãã©ã¡ãŒã¿ |
æåæã¯æçµçãªãªãã€ã¬ã¯ãå
ãå«ã Location ããããŒä»ãã® 302 Found ãè¿ããŸããã¹ããŒãæ€èšŒãšã«ãŒãããªããŒã¿ãŒã¯ãããŸããã
# LINE ãèªå¯åŸã«èªåçã«åŒã³åºããŸã
GET {{host}}/auth/oauth/line/callback?code=AUTHORIZATION_CODE&state=STATE_STRING
HTTP/1.1 302 Found
Location: https://example.com/auth/callback?onetimeToken=ONETIME_TOKEN
{ "error": { "message": "LINE authorization failed" } }
OAuth ãããŒã®è£è¶³:
purpose=oauth-loginã¯ãæ¢åã®å€éšãããã€ããŒã¢ã«ãŠã³ãã§ãã°ã€ã³ãããããŒã§ããpurpose=oauth-signupã¯ãæ°ããã¢ã€ãã³ãã£ãã£ãäœæãããããŒã§ãã- ãµã€ã³ã¢ããã§ã¯
typeIdãæå®ããŠãã ãããæå®ããªãå Žåããããã€ããŒã®ã³ãŒã«ããã¯ãå®äºã§ããŸããã redirectUrl㯠OAuth åŠçã®å®äºåŸã«ãŠãŒã¶ãŒãšãŒãžã§ã³ããæ»ã絶察 URL ã§ãããã®ãªãªãžã³ãoauth.allowedRedirectOriginsã«èšå®ããŠãã ãããfp㯠Google ãš LINE ã®éå§ãªã¯ãšã¹ãã§äœ¿çšããããã€ã¹ãã£ã³ã¬ãŒããªã³ãã§ãã- Twitter ã®éå§ãªã¯ãšã¹ãã§ã¯
fpãæå®ããŸããã - GoogleãTwitterãLINE ã®éå§ãšã³ããã€ã³ãã¯ãåãããã€ããŒã®èªå¯ URL ãž
302 Foundã§ãªãã€ã¬ã¯ãããŸãã - ã³ãŒã«ããã¯ãšã³ããã€ã³ãã¯ããããã€ããŒããè¿ãããèªå¯ã³ãŒããŸã㯠OAuth ããŒã¯ã³ãåŠçããŸãã
- Google ã®ã³ãŒã«ããã¯ã§ã¯ããããã€ããŒãçºè¡ãã
codeãšçœ²åä»ãã®stateã䜿çšããŸãã - Twitter ã®ã³ãŒã«ããã¯ã§ã¯ã
oauth_tokenãšoauth_verifierã䜿çšããŸãã - LINE ã®ã³ãŒã«ããã¯ã§ã¯ãèªå¯ã³ãŒã
codeãš CSRF ä¿è·çšã®stateã䜿çšããŸãã - ã³ãŒã«ããã¯ãæåãããšãæ€èšŒæžã¿ã®
redirectUrlã«onetimeTokenãä»ããŠãªãã€ã¬ã¯ããããŸããURL ã®ããŒã»ã³ããšã³ã³ãŒãã£ã³ã°ã¯ä¿æãããŸãã - OAuth ãããã€ããŒã§æ¢åã®ã¢ã€ãã³ãã£ãã£ãèŠã€ãããªãå ŽåããµãŒãã¹ã¯å¯Ÿå¿ãã
404ãšã©ãŒãè¿ããŸãã - ç¡å¹ãŸãã¯æéåãã®èªå¯æ
å ±ã¯
400ãšã©ãŒã«ãªããŸãã - OAuth èšå®ããããã€ããŒéä¿¡ã«å€±æããå Žåã¯
500ãšã©ãŒã«ãªããŸãã - OAuth ã®éå§ãšã³ãŒã«ããã¯ã¯ããªã¯ãšã¹ãããã£ãå¿ èŠãšããŸããã
redirectUrlã¯çµ¶å¯Ÿ URL ããã¯ãšãªãã©ã¡ãŒã¿ãŒãšã㊠1 åã ããšã³ã³ãŒãããŠãã ãããã¯ãšãªã·ãªã¢ã©ã€ã¶ãŒã«æž¡ãåã« URL å šäœããšã³ã³ãŒãããªãã§ãã ããã- ã³ãŒã«ãã㯠URL ã¯ãå OAuth ãããã€ããŒã®ã¢ããªã±ãŒã·ã§ã³èšå®ã«ç»é²ããå¿ èŠããããŸãã
- OAuth ã䜿çšãããã¹ãŠã®ç°å¢ã§ã空ã§ãªã
oauth.allowedRedirectOriginsãèšå®ããŠãã ãããèšå®ããªãå Žåã¯ãéå§ã»ã³ãŒã«ããã¯ã®ãªãã€ã¬ã¯ãæ€èšŒã500ã§å€±æããŸãã - èªèšŒããŒã¯ã³ããããã€ããŒã®èªå¯ã³ãŒãããã°ãžåºåããªãã§ãã ããã
- OAuth ã®éå§åã«ãåãããã€ããŒã®ã¯ã©ã€ã¢ã³ã IDãã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ãããã³ãŒã«ãã㯠URL ãèšå®ããŠãã ããã
- ãªãã€ã¬ã¯ãå ã§ã¯ãã¢ããªã±ãŒã·ã§ã³ãåãåã£ãèªèšŒçµæãå®å šã«åŠçããŠãã ããã
- åããŠãŒã¶ãŒãåããŠãã°ã€ã³ããå Žåã®ã¢ã€ãã³ãã£ãã£äœæã¯ããµãŒãã¹ã®èšå®ããã³
purposeã«åŸã£ãŠè¡ãããŸãã - æ¢åã¢ã«ãŠã³ããšã®é¢é£ä»ãã¯ããããã€ããŒåºæã®ãŠãŒã¶ãŒ ID ã䜿çšããŠå€å®ãããŸãã
- ãŠãŒã¶ãŒããããã€ããŒåŽã§èªå¯ãæåŠããå Žåãã¢ããªã±ãŒã·ã§ã³ã¯å€±æãããªãã€ã¬ã¯ããåŠçã§ããããã«ããŠãã ããã
stateã¯ãªã¯ãšã¹ãã«çŽã¥ãã³ã³ããã¹ããä¿æããã³ãŒã«ããã¯åŠçæã®æ€èšŒã«äœ¿çšãããŸãã- èªå¯ãããŒäžã«ãã©ãŠã¶ãŒãéããå ŽåããŠãŒã¶ãŒã¯éå§ãšã³ããã€ã³ãããå床ãããŒãå®è¡ã§ããŸãã
- å€éšãããã€ããŒã®èšå®å€ã¯ç°å¢å€æ°ãªã©ã®å®å šãªèšå®æ©æ§ã§ç®¡çããŠãã ããã
- OAuth 飿ºã倿ŽããåŸã¯ããã°ã€ã³ãšãµã€ã³ã¢ããã®äž¡æ¹ã®ãªãã€ã¬ã¯ããããŒããã¹ãããŠãã ããã
- ãšã©ãŒæã®ãªãã€ã¬ã¯ãå ã«ãããŠãŒã¶ãŒãå®å šã«å詊è¡ã§ããç»é¢ãçšæããŠãã ããã
- Google OAuth ã§ã¯ãGoogle ãçºè¡ããèªå¯ã³ãŒããããŒã¯ã³äº€æã«äœ¿çšããŸãã
- Twitter OAuth ã§ã¯ãOAuth ããŒã¯ã³ãšæ€èšŒåã®çµã¿åããã䜿çšããŸãã
- LINE OAuth ã§ã¯ãLINE ã®èªå¯ã³ãŒããããŒã¯ã³äº€æã«äœ¿çšããŸãã
LocationããããŒã¯ãã©ãŠã¶ãŒã«æ¬¡ã®é·ç§»å ãéç¥ããŸãã- OAuth ã®ãªãã€ã¬ã¯ãå¿ç㯠API JSON å¿çãšã¯ç°ãªããéåžžã¯ãã©ãŠã¶ãŒã§åŠçãããŸãã
- API ã¯ã©ã€ã¢ã³ãã§æ€èšŒããå Žåã¯ããªãã€ã¬ã¯ãã远跡ãã HTTP ã¯ã©ã€ã¢ã³ãã䜿çšããŠãã ããã
- èªå¯ã³ãŒãã¯çæéã§å€±å¹ãããããåãåã£ããéããã«ã³ãŒã«ããã¯åŠçãå®äºããŠãã ããã
- 倱æãã OAuth ãããŒãåå©çšããã®ã§ã¯ãªããæ°ããéå§ãªã¯ãšã¹ããçºè¡ããŠãã ããã
{ "error": { "message": "Identity creation failed" } }
{ "error": { "message": "No identity found for the given LINE account." } }
ã³ãŒã«ããã¯ãšã³ããã€ã³ãã¯çŽæ¥ã®ã¯ã©ã€ã¢ã³ãåŒã³åºãã§ã¯ãªããLINE ã®èªå¯åŠçããã®ãªãã€ã¬ã¯ãå ã§ãã
ð ã»ãã¥ãªãã£æ©èœâ
ã¢ã«ãŠã³ãä¿è·â
- ãã°ã€ã³å€±æåæ°ã®è¿œè·¡: 倱æåæ°ãèšé²
- ã¢ã«ãŠã³ãããã¯: èŠå®åæ°ïŒæ¢å®ã¯5åã倿Žå¯ïŒã§èªåããã¯
- ãã¹ã¯ãŒãããã·ã¥å: ãã¹ã¯ãŒãã¯å®å šã«ããã·ã¥å
- ããŒã¯ã³ã»ãã¥ãªãã£: ããã€ã¹æçŽãšIPæ€èšŒãå«ã
- OAuth ãªãã€ã¬ã¯ãæ€èšŒ: GoogleãLINEãTwitter ã®éå§ã«ãŒãã¯ããããã€ããŒãã©ã€ããŒãåŒã³åºãåã«ãªã¯ãšã¹ãã®ãªãã€ã¬ã¯ã URL ãæ€èšŒããŸããã³ãŒã«ããã¯ã¯ state ã®ãªãã€ã¬ã¯ãå
ãªãªãžã³ã
oauth.allowedRedirectOriginsã«å¯ŸããŠåæ€èšŒããŸããã³ãŒã«ããã¯ã®æ€èšŒã¯ããããã€ããŒã®ã³ãŒã«ããã¯åŠçãš state ã®åŠçåŸãSDK ã«ããã¢ã€ãã³ãã£ãã£ã®æ€æ»ã»æ€çŽ¢ã»äœæãããŒã¯ã³ã®çæã»ä¿åãæçµãªãã€ã¬ã¯ãããåã«å®è¡ãããŸãã
ããŒã¯ã³ç®¡çâ
- ã¢ã¯ã»ã¹ããŒã¯ã³: ç寿åœã®APIã¢ã¯ã»ã¹çšããŒã¯ã³
- ãªãã¬ãã·ã¥ããŒã¯ã³: åçºè¡çšã®é·å¯¿åœããŒã¯ã³
- ããŒã¯ã³æ€èšŒ: ãã¡ã€ã³ã»æçŽã»IPã»UA ãæ€èšŒ
- ã»ãã¥ã¢ã¯ãããŒ: HTTP-only/secure ã§å®å šã«ä¿å
èªèšŒæ¹æ³â
ãã¢ã©ãŒããŒã¯ã³â
// Use in Authorization header
Authorization: Bearer <access-token>
ã¯ãããŒèªèšŒâ
// Tokens automatically sent with requests
âïž èšå®ãªãã·ã§ã³â
ãµãŒãã¹èšå®â
interface AuthServiceConfig {
authSecrets?: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
maxFailedLoginAttempts?: number; // Default: 5
authMode?: 'bearer' | 'cookie';
checkIp?: boolean;
oauth?: {
allowedRedirectOrigins?: string[]; // OAuth ãªãã€ã¬ã¯ãã§èš±å¯ããããã³ããšã³ãã®ãªãªãžã³
};
cookieOpts?: {
domain?: string;
maxAge?: string | number;
path?: string;
sameSite?: 'strict' | 'lax' | 'none';
};
jwtOpts?: {
jwtSignOptions?: SignOptions;
stateful?: boolean;
};
accessTokenSignOptions?: SignOptions; // Default: {expiresIn: '15m'}
onetimeTokenSignOptions?: SignOptions; // Default: {expiresIn: '5m'}
refreshTokenSignOptions?: SignOptions; // Default: {expiresIn: '2d'}
isMfaEnabled?: boolean;
mfaCodeLength?: number;
mfaCodeEmailConfig?: {
sender: string;
emailConfig: {subject: string; bodyTemplate: string};
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
verifyEmailConfig?: {
enabled: boolean; // Enable email verification feature
emailConfig?: {
bodyTemplate: string; // Email body template with {{email}} and {{token}} placeholders
subject: string; // Email subject line
urlTemplate: string; // URL template with {{token}} placeholder
};
sender?: string; // Sender email address
};
invitation?: {
enabled: boolean; // Enable invitation feature
emailConfig?: {
bodyTemplate: string; // Email body template with {{email}} and {{token}} placeholders
subject: string; // Email subject line
urlTemplate: string; // URL template with {{token}} placeholder
sender: string; // Sender email address
};
target?: string; // Token target for invitation validation
};
}
èšå®è©³çްâ
èªèšŒãµãŒãã¹ã®èšå®ã¯ãã»ãã¥ãªãã£ã»ã¯ãããŒã»JWTã»æåŸ ã»ã¡ãŒã«ç¢ºèªã®è«çã°ã«ãŒãã«æŽçãããŠããŸãã
ð ã»ãã¥ãªãã£èšå®â
authSecrets - JWT ããŒã¯ã³ã®ã»ãã¥ãªãã£çšã·ãŒã¯ã¬ãã
- å:
{ authEncSecret: string; authSignSecret: string } - 説æ: JWT ã®æå·åã»çœ²åã«çšããã·ãŒã¯ã¬ããããŒ
- æ¢å®:
{ authEncSecret: '', authSignSecret: '' } - å¿ é : æ¬çªç°å¢ã§ã¯å¿ é
- åããããã£:
authEncSecret: JWT ãã€ããŒãæå·åçšã®ã·ãŒã¯ã¬ããauthSignSecret: JWT çœ²åæ€èšŒçšã®ã·ãŒã¯ã¬ãã
maxFailedLoginAttempts - ã¢ã«ãŠã³ãããã¯ã®ãããå€
- å:
number - 説æ: ããã¯ããããŸã§ã«èš±å®¹ããããã°ã€ã³å€±æåæ°ã®äžé
- æ¢å®:
5 - æå: ãããå€è¶ éã§ã¢ã«ãŠã³ããããã¯ïŒè§£é€ã¯æåïŒ
OAuth ãªãã€ã¬ã¯ãå ãªãªãžã³â
oauth.allowedRedirectOrigins - OAuth ãªãã€ã¬ã¯ãã§èš±å¯ããããã³ããšã³ãã®å®å
- å:
string[]ïŒAuthenticationServiceConfigurationã®ä»»æã®oauthãªããžã§ã¯ãå ã«ããä»»æã®ããããã£ïŒ - ããã©ã«ã:
undefinedãããã©ã«ãã®èš±å¯ãªã¹ãã¯ãããŸããã - å¿ é æ¡ä»¶: GoogleãLINEãTwitter ã® OAuth éå§ã»ã³ãŒã«ããã¯ã«ãŒãã䜿çšããå Žåã¯ã空ã§ãªãé åãå¿ èŠã§ããOAuth 以å€ã®èªèšŒã§ã¯ããã®ãã£ãŒã«ãã¯äžèŠã§ãã
- é
眮:
services.authServiceã®ç¬¬ 2 åŒæ°ã®configuration.oauth.allowedRedirectOriginsã - äŸ:
oauth: {allowedRedirectOrigins: ['https://example.com', 'http://localhost:3000']}
OAuth ã®éå§æã«æž¡ãããã³ããšã³ãã® redirectUrl ã«ã€ããŠããªãªãžã³ïŒã¹ããŒã ããã¹ãåãå¿
èŠã«å¿ããŠéããã©ã«ãããŒãïŒãèšå®ããŸããããã¯ããããã€ããŒã«ç»é²ããŠãã©ã€ããŒãã¡ã¯ããªãŒã«æž¡ãããã¯ãšã³ãã®ã³ãŒã«ãã㯠URL ãšã¯å¥ã®èšå®ã§ããäŸãã° http://localhost:3000/oauth/callback ã䜿çšããã«ã¯ããã®é
åã« http://localhost:3000 ãå¿
èŠã§ãã
以åã®èšå®ããç§»è¡ããå Žåã¯ããããã¬ãã«ã® frontendOrigins é
åã oauth.allowedRedirectOrigins ã«ç§»åããŠãã ãããéå§ã»ã³ãŒã«ããã¯ã«ãŒãã¯ãã¹ãããããã£ãŒã«ããåç
§ããæ§ãããã¬ãã«ã®ãã£ãŒã«ãã¯èš±å¯ãªã¹ããšããŠäœ¿çšãããŸãããoauth ãŸã㯠allowedRedirectOrigins ãæªèšå®ããããã¯é
åã空ã®å Žåãæ€èšŒã¯ AuthenticationUnexpectedError ãè¿ããŸããéå§ã»ã³ãŒã«ããã¯ã«ãŒãã¯ããããããã®ãšã©ãŒã 500 ã«å¯Ÿå¿ä»ããŸãã
validateURL ãã«ããŒã¯ãå®å
ã®ãªãªãžã³ãæ€æ»ããŸãããã¹ãã¯ã€ã«ãã«ãŒããå«ãŸãªãæç€ºçãªãªãªãžã³ãæå®ããŠãã ãããåèšå®å€ã¯å°æåã«å€æãããæ«å°Ÿã®ã¹ã©ãã·ã¥ã 1 ã€é€å»ããŠããæ¯èŒãããŸãããµããã¡ã€ã³ãç°ãªãããŒãã«ã¯ãåå¥ã®èšå®ãå¿
èŠã§ããèšå®ãæªæå®ãŸãã¯ç©ºã®å Žåãéå§ã»ã³ãŒã«ããã¯ã®æ€èšŒã¯ãªãã€ã¬ã¯ããæåŠããŸãã
SDK 0.15.0 ãžã®ã¯ã©ã€ã¢ã³ãç§»è¡ã§ã¯ãéåžžã®çµ¶å¯Ÿ URL ã redirectUrl ãšããŠã¯ãšãªã·ãªã¢ã©ã€ã¶ãŒã«æž¡ãããã©ã¡ãŒã¿ãŒã 1 åã ããšã³ã³ãŒãããŠãã ãããURLSearchParams ã䜿ãåã« URL å
šäœããšã³ã³ãŒãããªãã§ãã ããããã©ãŠã¶ãŒãããŒãåç
§ããŠãã ããããªãã€ã¬ã¯ããã«ããŒã¯ãåŸãããå®å
æååãä¿æããå床ãã³ãŒãããã« onetimeToken ã远å ããŸãã
ð å€èŠçŽ èªèšŒïŒMFAïŒèšå®â
isMfaEnabled ã¯ãã°ã€ã³æã®å€èŠçŽ èªèšŒãæå¹ã«ããŸããå㯠booleanãæ¢å®å€ã¯ false ã§ããæå¹æã¯è³æ Œæ
å ±ã®æ€èšŒåŸã«ã¡ãŒã«ã§éä¿¡ããã³ãŒãã®æ€èšŒãèŠæ±ãããããmfaCodeEmailConfig ã®èšå®ãå¿
èŠã§ãã
mfaCodeLength ã¯çæãã MFA ã³ãŒãã®æ¡æ°ã§ããå㯠numberãæ¢å®å€ã¯ 6 ã§ããã³ãŒãã¯å
é ã®ãŒããå«ã¿ããæ°å€æååïŒäŸ: "012345"ïŒã§ãã
onetimeTokenSignOptions 㯠MFA ãã£ã¬ã³ãžãå«ãã¯ã³ã¿ã€ã ããŒã¯ã³ã®æå¹æéãèšå®ããŸããexpiresIn ãå¿
é ã§ãæ¢å®å€ã¯ { expiresIn: '5m' } ã§ãã
mfaCodeEmailConfig 㯠MFA ã³ãŒãéä¿¡çšã¡ãŒã«èšå®ã§ããå㯠{ sender: string; emailConfig: { subject: string; bodyTemplate: string } } ã§ãMFA ãæå¹ã«ããå Žåã¯å¿
é ã§ããbodyTemplate ã§ã¯ ${code} ãã¬ãŒã¹ãã«ããŒã䜿çšã§ããŸãã
MFA ãããŒ: è³æ Œæ
å ±ã®æ€èšŒåŸããµãŒãã¹ã¯æéä»ããã£ã¬ã³ãžããŒã¯ã³ãšæ°å€ã³ãŒããçæããã¡ãŒã«ã§ã³ãŒããéä¿¡ããŸããã¯ã©ã€ã¢ã³ãã¯ããŒã¯ã³ãšã³ãŒãã /auth/mfa/verify ã«éä¿¡ããæ€èšŒãæåãããšã¢ã¯ã»ã¹ããŒã¯ã³ãšãªãã¬ãã·ã¥ããŒã¯ã³ãåãåããŸãã
ðª ã¯ãããŒèšå®â
cookieOpts - HTTP ã¯ãããŒèšå®
- å:
{ domain?: string; maxAge?: string | number; path?: string; sameSite?: 'strict' | 'lax' | 'none' } - 説æ: èªèšŒããŒã¯ã³ã®ãã©ãŠã¶ã¯ãããŒã§ã®ä¿åæ¹æ³ãå¶åŸ¡
- æ¢å®:
undefinedïŒããŒã¯ã³ã®æå¹æéã«æºæ ïŒ - åããããã£:
domain: ã¯ãããŒã®ãã¡ã€ã³ç¯å²- å:
string - 説æ: ãµããã¡ã€ã³æšªæã®ç¯å²ãå¶åŸ¡
- äŸ:
'.example.com'ïŒå šãµããã¡ã€ã³ïŒ
- å:
maxAge: ã¯ãããŒã®æå¹æé- å:
string | number - 説æ: æå¹æéïŒããªç§ïŒ
- å:
path: ã¯ãããŒã®ãã¹ç¯å²- å:
string - 説æ: ç¹å®ãã¹ã«éå®
- æ¢å®:
'/'ïŒãã¡ã€ã³å šäœïŒ - äŸ:
'/api'ïŒAPI ã®ã¿ïŒ
- å:
sameSite: CSRF ä¿è·ã¬ãã«- å:
'strict' | 'lax' | 'none' - 説æ: ã¯ãã¹ãµã€ããªã¯ãšã¹ãã§ã¯ãããŒãéä¿¡ãããæ¡ä»¶
- å€:
'strict': åäžãµã€ãã®ã¿éä¿¡ïŒæã峿 ŒïŒ'lax': ããã²ãŒã·ã§ã³æã«éä¿¡ïŒãã©ã³ã¹ïŒ'none': ãã¹ãŠã®ã¯ãã¹ãµã€ãã§éä¿¡ïŒsecure: trueå¿ é ïŒ
- å:
ð JWT èšå®â
jwtOpts - JWT çæ/æ€èšŒãªãã·ã§ã³
- å:
{ jwtSignOptions?: SignOptions; stateful?: boolean } - 説æ: JWT 眲å/æ€èšŒã®æåãã«ã¹ã¿ãã€ãº
- æ¢å®:
undefinedïŒæšæºèšå®ïŒ - åããããã£:
jwtSignOptions: JWT 眲åèšå®- å:
SignOptionsïŒjsonwebtokenïŒ - 説æ: 眲åã¢ã«ãŽãªãºã ããã©ã¡ãŒã¿ã®èª¿æŽ
- æ¢å®: æšæºçœ²å
- å:
stateful: ãµãŒããŒåŽããŒã¯ã³æ€èšŒ- å:
boolean - 説æ: 倱å¹ç®¡çãªã©ã®åŒ·åã®ãããµãŒããŒåŽã§æ€èšŒ
- æ¢å®:
falseïŒã¹ããŒãã¬ã¹ïŒ - çšé: ããŒã¯ã³å€±å¹ãšã»ãã¥ãªãã£åŒ·å
- å:
â° ããŒã¯ã³æå¹æéâ
accessTokenExpireTime - ã¢ã¯ã»ã¹ããŒã¯ã³å¯¿åœ
- å:
stringïŒms 圢åŒïŒ - 説æ: API ã¢ã¯ã»ã¹çšã®ç寿åœããŒã¯ã³
- æ¢å®:
undefined - 圢åŒ:
'30m','1h','2h'ãªã©ïŒms 圢åŒïŒ - ã»ãã¥ãªãã£: é²åºæéãæå°å
refreshTokenExpireTime - ãªãã¬ãã·ã¥ããŒã¯ã³å¯¿åœ
- å:
stringïŒms 圢åŒïŒ - 説æ: åçºè¡çšã®é·å¯¿åœããŒã¯ã³
- æ¢å®:
undefined - 圢åŒ:
'1d','7d','30d'ãªã©ïŒms 圢åŒïŒ - ã»ãã¥ãªãã£: HTTP-only/secure ã¯ãããŒã«ä¿å
onetimeTokenExpireTime - ã¯ã³ã¿ã€ã ããŒã¯ã³å¯¿åœ
- å:
stringïŒms 圢åŒïŒ - 説æ: ãã¹ã¯ãŒãåèšå®ã»ã¡ãŒã«ç¢ºèªçšã®äžæããŒã¯ã³
- æ¢å®:
undefined - 圢åŒ:
'15m','1h','2h'ãªã©ïŒms 圢åŒïŒ - ã»ãã¥ãªãã£: 1åéãã»ç寿åœ
ð§ ã¡ãŒã«ç¢ºèªèšå®â
verifyEmailConfig - ã¡ãŒã«ç¢ºèªã®èšå®
- å:
{ enabled: boolean; emailConfig?: EmailConfig; mailService?: MailService; sender: string } - 説æ: ã¡ãŒã«ç¢ºèªæ©èœãšãã³ãã¬ãŒããå¶åŸ¡
- æ¢å®:
undefinedïŒã¡ãŒã«ç¢ºèªã¯ç¡å¹ïŒ - åããããã£:
enabled: ã¡ãŒã«ç¢ºèªæ©èœãæå¹å- å:
boolean - 説æ: ã¡ãŒã«ç¢ºèªæ©èœã®ãã¹ã¿ãŒã¹ã€ãã
- æ¢å®:
false - å¿ é : ã¡ãŒã«ç¢ºèªã䜿çšããå Žåã¯å¿ é
- å:
emailConfig: ã¡ãŒã«ãã³ãã¬ãŒãèšå®- å:
{ bodyTemplate: string; subject: string; urlTemplate: string } - 説æ: 確èªã¡ãŒã«ã®ãã³ãã¬ãŒã
- å¿ é : æå¹ãªå Žåã«å¿ é
- åããããã£:
bodyTemplate: HTML ã¡ãŒã«æ¬æãã³ãã¬ãŒã- å:
string - 説æ: æ¬æã® HTML ãã³ãã¬ãŒãã
{{url}},{{email}},{{token}}ã䜿çšå¯èœãurlã«ã¯urlTemplateã®å€ãé©çš - äŸ:
"Hello {{email}}, click <a href=\"{{url}}\">here</a> to verify your email."
- å:
subject: ã¡ãŒã«ä»¶å- å:
string - 説æ: 確èªã¡ãŒã«ã®ä»¶å
- äŸ: "Verify your email address"
- å:
urlTemplate: 確èªãªã³ã¯ã® URL ãã³ãã¬ãŒã- å:
string - 説æ:
{{email}}ãš{{token}}ãã¬ãŒã¹ãã«ããå«ã URL ãã³ãã¬ãŒã - äŸ: "https://yourapp.com/verify?token={{token}}"
- å:
- å:
sender: éä¿¡è ã¡ãŒã«ã¢ãã¬ã¹- å:
string - 説æ: 確èªã¡ãŒã«ã®éä¿¡å ã¢ãã¬ã¹
- å¿ é : ãããïŒä»»æïŒ
- äŸ: "noreply@yourapp.com"
- å:
| ã¹ããŒã¿ã¹ | ãšã©ãŒã¡ãã»ãŒãž | 説æ |
|---|---|---|
| 400 | Validation Error | ãªã¯ãšã¹ãããã£ã®åœ¢åŒãäžæ£ |
| 400 | verification email feature not enabled | ã¡ãŒã«ç¢ºèªãæªèšå® |
| 400 | verification email feature requires a mail service to be provided | ã¡ãŒã«éä¿¡ãµãŒãã¹ãæªèšå® |
| 400 | verifyEmailConfig requires emailConfig with fields bodyTemplate, subject, urlTemplate | ã¡ãŒã«èšå®ãäžè¶³ |
| 400 | Unable to verify token | 確èªããŒã¯ã³ãæ€èšŒã§ããªã |
| 401 | wrong credentials provided | ã¡ãŒã«/ãã¹ã¯ãŒããäžæ£ |
| 401 | This account is locked | 倱æåæ°è¶ éã«ããããã¯æžã¿ |
| 401 | Token is not valid access token | ç¡å¹ãŸãã¯æéåãã®ããŒã¯ã³ |
| 401 | Token fails security check | ããŒã¯ã³ã®ã»ãã¥ãªãã£æ€èšŒã«å€±æ |
| 401 | token could not be verified | èªå¯ããŒã¯ã³ããªã/ç¡å¹ |
| 403 | token does not contain expected data | ããŒã¯ã³ã®å 容ãæåŸ å€ã«äžèŽããªã |
| 403 | User is not authorized to access this resource | æš©éäžè¶³ïŒç®¡çè ã¢ã¯ã»ã¹ãå¿ èŠïŒ |
| 404 | User not found | ãŠãŒã¶ãŒãååšããªã |
| 404 | Invitation not found | æåŸ ãååšããªã |
| 409 | Email already verified or no changes made | ã¡ãŒã«ã¯æ¢ã«ç¢ºèªæžã¿ |
| 422 | unable to register "email" | ã¡ãŒã«ã¢ãã¬ã¹ã¯æ¢ã«ååš |
| 500 | unable to generate access token | ã¢ã¯ã»ã¹ããŒã¯ã³ã®çæã«å€±æ |
| 500 | unable to generate refresh token | ãªãã¬ãã·ã¥ããŒã¯ã³ã®çæã«å€±æ |
| 500 | Failed to send verification email | 確èªã¡ãŒã«ã®éä¿¡ã«å€±æ |
| 400/500 | Failed to create invitation | æåŸ ã®äœæã«å€±æ |
ð ãã¹ã¯ãŒãåèšå®ã¡ãŒã«èšå®â
sendResetPasswordEmailConfig ã¯ãã¹ã¯ãŒãåèšå®ã¡ãŒã«ã®ãã³ãã¬ãŒããšéä¿¡è
ãèšå®ããŸããå㯠{ emailConfig: EmailConfig; sender: string } ã§ããemailConfig ã® bodyTemplateãsubjectãurlTemplate ã¯å¿
é ã§ãurlTemplate ã§ã¯ ${token} ã䜿çšã§ããŸããæ¢å®ã®æ¬æã¯ Reset your password by clicking ${url} ã§ãã
resetPasswordSuccessConfig ã¯ãã¹ã¯ãŒãåèšå®æåéç¥ã®ãã³ãã¬ãŒããšéä¿¡è
ãèšå®ããŸããæ¢å®ã®æ¬æã¯ Your password has been reset ã§ãã
changePasswordConfig ã¯ãã¹ã¯ãŒã倿Žéç¥ã®ãã³ãã¬ãŒããšéä¿¡è
ãèšå®ããŸããæ¢å®ã®æ¬æã¯ Your password has been changed ã§ãã
deactivateIdentityEmailConfig ã¯ã¢ã«ãŠã³ãç¡å¹åéç¥ã®ãã³ãã¬ãŒããšéä¿¡è
ãèšå®ããŸãããµãŒãã¹ã«ã¯æ¢å®å€ããªããããç¡å¹åã¡ãŒã«ãå¿
èŠãªå Žåã¯èšå®ãæå®ããŠãã ããã
ãµãŒãã¹ãªãã·ã§ã³ïŒç¬¬3åŒæ°ïŒâ
interface AuthServiceOptions {
mailService?: MailService; // Mail service implementation
googleOAuthDriver?: GoogleOAuthDriver; // Google OAuth driver instance
}
ããã㯠authService(dataStores, config, options) ã®ç¬¬3åŒæ°ã§æå®ããŸãã
ðš æåŸ èšå®â
invitation - æåŸ
æ©èœã®èšå®
- å:
{ enabled: boolean; emailConfig?: InvitationEmailConfig; target: string } - 説æ: æåŸ æ©èœãšã¡ãŒã«ãã³ãã¬ãŒããå¶åŸ¡
- æ¢å®:
undefinedïŒæåŸ ã«ãŒãã¯ç»é²ããããŸãŸã§ããæåŸ ã®äœæã«ã¯æå¹ãªã¡ãŒã«èšå®ãšã第 3 åŒæ°ãªãã·ã§ã³ã®mailServiceãå¿ èŠã§ãïŒ - åããããã£:
enabled: æåŸ æ©èœãæå¹å- å:
boolean - 説æ: æåŸ äœææã®ã¡ãŒã«éä¿¡ã«å¿ èŠã§ãã
- æ¢å®:
false - å¿ é : æåŸ æ©èœã䜿çšããå Žåã¯å¿ é
- å:
emailConfig: æåŸ ã¡ãŒã«ã®ãã³ãã¬ãŒãèšå®- å:
{ bodyTemplate: string; subject: string; urlTemplate: string; sender: string } - 説æ: æåŸ ã¡ãŒã«ã®ãã³ãã¬ãŒã
- å¿ é : æåŸ äœæã®æåã«å¿ èŠã§ããæå®ããå Žåã¯å éšãã£ãŒã«ããå¿ é ã§ãã
- åããããã£:
bodyTemplate: HTML ã¡ãŒã«æ¬æãã³ãã¬ãŒã- å:
string - 説æ: æ¬æã® HTML ãã³ãã¬ãŒãã
{{url}},{{token}},{{email}}ã䜿çšå¯èœãurlã«ã¯urlTemplateã®å€ãé©çš - äŸ:
"<h1>You're invited!</h1><p>Click <a href='{{url}}'>here</a> to accept the invitation.</p>"
- å:
subject: ã¡ãŒã«ä»¶å- å:
string - 説æ: æåŸ ã¡ãŒã«ã®ä»¶å
- äŸ:
"You're invited to join our organization"
- å:
urlTemplate: æåŸ ãªã³ã¯ã® URL ãã³ãã¬ãŒã- å:
string - 説æ:
{{token}}ãš{{email}}ãã¬ãŒã¹ãã«ããå«ã URL ãã³ãã¬ãŒã - äŸ:
"https://yourapp.com/invitations/accept?token={{token}}&email={{email}}"
- å:
sender: éä¿¡è ã¡ãŒã«ã¢ãã¬ã¹- å:
string - 説æ: æåŸ ã¡ãŒã«ã®éä¿¡å ã¢ãã¬ã¹
- å¿ é : æå¹ãªå Žåã«å¿ é
- äŸ:
"invites@yourapp.com"
- å:
- å:
target: æåŸ æ€èšŒçšããŒã¯ã³ã®ã¿ãŒã²ãã- å:
string - 説æ: æåŸ ããŒã¯ã³æ€èšŒã®ã¿ãŒã²ããèå¥å
- æ¢å®:
"invitation" - å¿ é : ããã
- äŸ:
"invitation"
- å:
èšå®äŸâ
const authConfig = {
oauth: {allowedRedirectOrigins: ['https://yourapp.com', 'http://localhost:3000']},
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
maxFailedLoginAttempts: 3,
cookieOpts: {
secure: true,
sameSite: 'strict',
maxAge: 2 * 24 * 60 * 60 * 1000 // 2 days
},
accessTokenExpireTime: '1h',
refreshTokenExpireTime: '7d',
onetimeTokenExpireTime: '30m',
verifyEmailConfig: {
enabled: true,
emailConfig: {
bodyTemplate: 'Hello {{email}}, click <a href="{{url}}">here</a> to verify your email address.',
subject: 'Verify your email address',
urlTemplate: 'https://yourapp.com/verify?token={{token}}'
},
sender: 'noreply@yourapp.com'
},
invitation: {
enabled: true,
emailConfig: {
bodyTemplate: '<h1>You\'re invited!</h1><p>Click <a href="{{url}}">here</a> to accept the invitation.</p>',
subject: 'You\'re invited to join our organization',
urlTemplate: 'https://yourapp.com/invitations/accept?token={{token}}&email={{email}}',
sender: 'invites@yourapp.com'
},
target: 'invitation'
}
};
ðš ãšã©ãŒãã³ããªã³ã°â
èªèšŒé¢é£ã®ãšã©ãŒã¯ãé©åãªHTTPã¹ããŒã¿ã¹ã³ãŒããšJSON圢åŒã§è¿ãããŸãã
代衚çãªãšã©ãŒã³ãŒãâ
| ã¹ããŒã¿ã¹ | ãšã©ãŒã¡ãã»ãŒãž | 説æ |
|---|---|---|
| 400 | Invalid redirect URL | OAuth ã®éå§ã»ã³ãŒã«ããã¯ã®ãªãã€ã¬ã¯ã URL ã絶察 URL ãšããŠè§£æã§ããŸããã |
| 400 | Redirect URL origin '<origin>' is not allowed | OAuth ã®éå§ã»ã³ãŒã«ããã¯ã®å®å
ãªãªãžã³ã oauth.allowedRedirectOrigins ã«å«ãŸããŠããŸããã |
| 500 | No origins to check against | OAuth ã®éå§ã»ã³ãŒã«ããã¯ã§ oauth.allowedRedirectOrigins ãæªèšå®ãŸãã¯ç©ºã§ãã |
| 400 | Validation Error | ãªã¯ãšã¹ãæ¬æã®åœ¢åŒãç¡å¹ |
| 400 | verification email feature not enabled | ã¡ãŒã«èªèšŒãèšå®ãããŠããªã |
| 400 | verification email feature requires a mail service to be provided | ã¡ãŒã«ãµãŒãã¹ãèšå®ãããŠããªã |
| 400 | verifyEmailConfig requires emailConfig with fields bodyTemplate, subject, urlTemplate | ã¡ãŒã«èšå®ãäžè¶³ããŠãã |
| 400 | Unable to verify token | èªèšŒããŒã¯ã³ãç¡å¹ |
| 401 | wrong credentials provided | ã¡ãŒã«ã¢ãã¬ã¹ãŸãã¯ãã¹ã¯ãŒããç¡å¹ |
| 401 | This account is locked | 倱æåæ°ã«ããã¢ã«ãŠã³ããããã¯ãããŠãã |
| 401 | Token is not valid access token | ããŒã¯ã³ãç¡å¹ãŸãã¯æéåã |
| 401 | Token fails security check | ããŒã¯ã³ã®ã»ãã¥ãªãã£æ€èšŒã«å€±æ |
| 401 | Unable to detect access token | ã¢ã¯ã»ã¹ããŒã¯ã³ããªã |
| 403 | token does not contain expected data | ããŒã¯ã³ã®æ€èšŒã«å€±æ |
| 403 | Identity is not authorized to access this resource | ã¢ã€ãã³ãã£ãã£ã«å¿ èŠãªæš©éïŒç®¡çè ã¢ã¯ã»ã¹ïŒããªã |
| 404 | Identity not found | ã¢ã€ãã³ãã£ãã£ãååšããªã |
| 404 | Invitation not found | æåŸ ãååšããªã |
| 409 | Email already verified or no changes made | ã¡ãŒã«ã¢ãã¬ã¹ã¯ãã§ã«èªèšŒæžã¿ |
| 422 | unable to register "<email>" | ã¡ãŒã«ã¢ãã¬ã¹ããã§ã«ååšãã |
| 500 | unable to generate access token | ããŒã¯ã³ã®çæã«å€±æ |
| 500 | unable to generate refresh token | ãªãã¬ãã·ã¥ããŒã¯ã³ã®çæã«å€±æ |
| 500 | Failed to send verification email | ã¡ãŒã«éä¿¡åŠçã«å€±æ |
| 500 | Invitation email configuration is incomplete or disabled | æåŸ ã¡ãŒã«èšå®ãŸãã¯ã¡ãŒã«ãµãŒãã¹ãå©çšã§ããªã |
ãšã©ãŒã¬ã¹ãã³ã¹åœ¢åŒâ
以äžã¯åå¥ã®èªèšŒãããŒã§è¿ããã代衚çãªãšã©ãŒãã€ããŒãã§ããmessage ã¯ãµãŒããŒããè¿ãããæè¡ãªãã©ã«ã®ãã倿ŽããŸããã
{ "error": { "message": "wrong credentials provided" } }
{ "error": { "message": "This account is locked" } }
{ "error": { "message": "Token is not valid access token" } }
{ "error": { "message": "Token fails security check" } }
{ "error": { "message": "token does not contain expected data" } }
{ "error": { "message": "Invitation not found" } }
{ "error": { "message": "Email already verified or no changes made" } }
{ "error": { "message": "unable to generate access token" } }
{ "error": { "message": "unable to generate refresh token" } }
{ "error": { "message": "Failed to create invitation" } }
{ "error": { "message": "Unable to verify token" } }
{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}
ð é¢é£ããã¥ã¡ã³ãâ
- ãããã£ãŒã«ãµãŒãã¹ - ãããã£ãŒã«ç®¡ç
- ãšã©ãŒãã³ããªã³ã° - ãšã©ãŒããã«ãŠã§ã¢ãšåŠç