Skip to main content

Authentication

Start a login, exchange the code for a session token, validate or end a session, and manage a member's own sessions.

Project-scoped login (/auth/authorize), backend-to-backend session API (/auth/token, /auth/validate, /auth/logout, /auth/token/refresh), and system-admin Discord OAuth (/auth/admin/*). Use /auth/authorize when you need to force a fresh Discord consent (step-up auth) or to stay on the pre-SSO flow.

Initiate authorization request (legacy / force re-auth)

GET/api/auth/authorize

Always bounces through Discord OAuth, even if the browser already holds a valid mcdi_sso cookie. Use this when you need fresh Discord consent (step-up auth, admin operations) or to keep a pre-SSO integration unchanged. For the default login button, prefer GET /auth/sso/authorize - it skips the Discord screen for returning users.

The platform redirects the user here with client_id, redirect_uri, server_id, and state as query parameters. MCDI validates the params, creates a short-lived auth request in the DB, sets an httpOnly cookie with the request ID, and redirects to Discord OAuth.

Authentication: None, this endpoint is public.

Parameters

NameInTypeRequiredDescription
client_idquerystring (uuid)yesProject ID (UUID) identifying the client application
redirect_uriquerystringyesURI to redirect back to after authentication. Must be whitelisted for the project.
server_idquerystringyesDiscord server ID to verify membership against
statequerystringyesOpaque state value passed through to the redirect. Use for CSRF protection.

Responses

StatusDescriptionBody
200object
302Redirects to Discord OAuth authorization page.
400Invalid or missing query parameters.
403Project inactive, redirect URI not allowed, or server not accessible.

Open in Swagger (opens in a new tab)

Redirect to Discord OAuth

GET/api/auth/discord

Reads the auth request ID from the httpOnly mcdi_auth_req cookie set by GET /auth/authorize. Resolves the request, marks it as used, and redirects to Discord OAuth.

Authentication: None, this endpoint is public.

Responses

StatusDescriptionBody
200object
302Redirects to Discord OAuth authorization page.

Open in Swagger (opens in a new tab)

Invalidate session token (project-scoped)

POST/api/auth/logout

External platforms call this when their user logs out to invalidate the MCDI session token.

Requires a valid X-API-Key header. Only sessions belonging to the calling project are deleted - tokens from other projects are ignored.

Authentication: Project API key (X-API-Key header)

Request body (JSON, required): LogoutDto schema.

Responses

StatusDescriptionBody
200Logout successful.SuccessResponseDto
400Invalid request body (e.g. empty token).

Open in Swagger (opens in a new tab)

Invalidate all sessions for a member (project-scoped)

POST/api/auth/logout-all

Invalidates all session tokens for a member within the calling project. Requires a valid X-API-Key header. Only sessions belonging to the calling project are affected.

Authentication: Project API key (X-API-Key header)

Request body (JSON, required): LogoutAllDto schema.

Responses

StatusDescriptionBody
200All sessions invalidated.SuccessResponseDto
400Invalid request body (e.g. empty memberId).

Open in Swagger (opens in a new tab)

List active sessions for the current member

GET/api/auth/sessions

Returns the authenticated member's non-expired sessions, including the client metadata captured when each session was created. Token material is never returned.

Authentication: Admin session token (Authorization: Bearer <token>)

Responses

StatusDescriptionBody
200Active sessions for the current member.SessionListResponseDto
401Missing, invalid, or expired session token.
429Too many requests - retry after a short delay.

Open in Swagger (opens in a new tab)

Revoke a specific session

DELETE/api/auth/sessions/{sessionId}

Immediately revokes one of the current member's sessions. The next request using that token will fail. A session that does not exist or belongs to another member is reported as not found.

Authentication: Admin session token (Authorization: Bearer <token>)

Parameters

NameInTypeRequiredDescription
sessionIdpathstringyes

Responses

StatusDescriptionBody
204Session revoked.
401Missing, invalid, or expired session token.
404Session not found for the current member.
429Too many requests - retry after a short delay.

Open in Swagger (opens in a new tab)

Exchange callback code for session token (backend-to-backend)

POST/api/auth/token

External platforms call this from their backend to exchange the short-lived code received in the redirect for a final, long-lived session token.

Requires a valid X-API-Key header. The code must belong to the project associated with the API key.

Authentication: Project API key (X-API-Key header)

Request body (JSON, required): ExchangeCodeDto schema.

Responses

StatusDescriptionBody
200Exchange successful - returns a long-lived session token.TokenResponseDto
400Invalid request body.
401Invalid or expired callback code, or project mismatch.
429Too many exchange requests - retry after a short delay.

Open in Swagger (opens in a new tab)

Refresh an active session token

POST/api/auth/token/refresh

Rotates an active session. The caller presents the still-valid session token (as a Bearer token) plus its matching refresh token in the body. A new access token and a new refresh token are issued and the expiry is extended - the previous pair is invalidated immediately.

Authentication: Admin session token (Authorization: Bearer <token>)

Request body (JSON, required): RefreshTokenDto schema.

Responses

StatusDescriptionBody
200Session refreshed - new access and refresh tokens.RefreshTokenResponseDto
400Invalid request body (e.g. empty refresh token).
401Invalid/expired session token or refresh token.
429Too many refresh requests - retry after a short delay.

Open in Swagger (opens in a new tab)

Validate session token (project-scoped)

POST/api/auth/validate

External platforms call this to validate a session token and retrieve current member information + their roles. Roles are fetched live from the DB so they always reflect the latest state.

Requires a valid X-API-Key header. Only sessions belonging to the calling project are resolved - tokens from other projects are treated as invalid.

Authentication: Project API key (X-API-Key header)

Request body (JSON, required): ValidateSessionDto schema.

Responses

StatusDescriptionBody
200Session valid - member + roles.ValidateSessionResponseDto
400Invalid request body (e.g. empty token).
401Invalid or expired session token.
429Too many validation requests - retry after a short delay.

Open in Swagger (opens in a new tab)

Schemas

AuthMemberProfileDto schema

FieldTypeRequiredDescription
avatarstring or nullnoAvatar URL
displayNamestring or nullnoServer nickname
emailstring or nullnoPrimary email associated with the Discord account
globalNamestring or nullnoGlobal display name
idstringyesDiscord user ID
isClubMemberbooleanyesWhether the member is in the main club server
joinedAtstring (date-time) or nullnoDate the member joined Discord
usernamestringyesDiscord username

AuthMemberResponseDto schema

FieldTypeRequiredDescription
avatarstring or nullnoAvatar URL or hash
createdAtstring (date-time)yesCreation timestamp
displayNamestring or nullnoDisplay name
emailstring or nullnoEmail address
globalNamestring or nullnoDiscord global name
idstringyesMember ID (Discord ID)
isClubMemberbooleanyesWhether the user is a club member
joinedAtstring (date-time) or nullnoDate when the user joined
syncedAtstring (date-time) or nullnoLast sync with Discord
updatedAtstring (date-time)yesLast update timestamp
usernamestringyesDiscord username

AuthMemberRoleDto schema

FieldTypeRequiredDescription
roleColornumber or nullnoRole color in decimal
roleIdstringyesRole ID
roleNamestringyesRole name
rolePositionnumber or nullnoRole position (higher = more permissions)

ExchangeCodeDto schema

FieldTypeRequiredDescription
clientIdstringyesProject ID (clientId) that issued the code
codestringyesThe one-time exchange code received from the redirect
redirectUristringyesThe same redirect_uri that was used in the authorize call

LogoutAllDto schema

FieldTypeRequiredDescription
memberIdstringyesMember ID (Discord ID) to logout from all devices

LogoutDto schema

FieldTypeRequiredDescription
tokenstringyesSession token to invalidate

RefreshTokenDto schema

FieldTypeRequiredDescription
refreshTokenstringyesThe current refresh token issued alongside the session

RefreshTokenResponseDto schema

FieldTypeRequiredDescription
accessTokenstringyesNew session (access) token replacing the previous one
expiresAtstring (date-time)yesISO 8601 timestamp when the new access token expires
refreshTokenstringyesNew refresh token - the previous one is now invalid

RoleResponseDto schema

FieldTypeRequiredDescription
roleColornumber or nullnoRole color (integer)
roleIdstringyesDiscord role ID
roleNamestringyesRole name
rolePositionnumber or nullnoRole position in the hierarchy

SessionClientInfoDto schema

FieldTypeRequiredDescription
ipAddressstring or nullnoIP address captured when the session was created
userAgentstring or nullnoUser agent captured when the session was created

SessionListItemDto schema

FieldTypeRequiredDescription
clientInfoSessionClientInfoDtonoClient metadata captured at session creation
createdAtstring (date-time)yesWhen the session was created
expiresAtstring (date-time)yesWhen the session expires
idstringyesSession ID
projectIdstring or nullnoProject this session was created for
serverIdstring or nullnoDiscord server the session was verified against

SessionListResponseDto schema

FieldTypeRequiredDescription
sessionsarray of SessionListItemDtoyesActive sessions for the authenticated member

SuccessResponseDto schema

FieldTypeRequiredDescription
successbooleanyesOperation success status

TokenResponseDto schema

FieldTypeRequiredDescription
expiresAtstring (date-time)yesISO 8601 timestamp when the token expires
memberAuthMemberProfileDtoyesBasic profile information for the authenticated member
refreshTokenstringyesRefresh token used to rotate this session via POST /auth/token/refresh
rolesarray of AuthMemberRoleDtoyesList of roles the member has in the associated server
tokenstringyesLong-lived session token (Bearer token)

ValidateSessionDto schema

FieldTypeRequiredDescription
tokenstringyesSession token

ValidateSessionResponseDto schema

FieldTypeRequiredDescription
memberAuthMemberResponseDtoyesAuthenticated member
rolesarray of RoleResponseDtoyesMember's roles in the verified Discord server

Source: apps/api/openapi.json.