@mulverse/mulguard-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/adapters.d.ts +522 -0
- package/adapters.d.ts.map +1 -0
- package/adapters.js +170 -0
- package/errors.d.ts +429 -0
- package/errors.d.ts.map +1 -0
- package/errors.js +473 -0
- package/index.d.ts +547 -0
- package/index.d.ts.map +1 -0
- package/index.js +142 -0
- package/jwt.d.ts +132 -0
- package/jwt.d.ts.map +1 -0
- package/jwt.js +123 -0
- package/lib/actions/callback/handle-login.d.ts +35 -0
- package/lib/actions/callback/handle-login.d.ts.map +1 -0
- package/lib/actions/callback/handle-login.js +275 -0
- package/lib/actions/callback/index.d.ts +5 -0
- package/lib/actions/callback/index.d.ts.map +1 -0
- package/lib/actions/callback/index.js +409 -0
- package/lib/actions/callback/oauth/callback.d.ts +36 -0
- package/lib/actions/callback/oauth/callback.d.ts.map +1 -0
- package/lib/actions/callback/oauth/callback.js +248 -0
- package/lib/actions/callback/oauth/checks.d.ts +70 -0
- package/lib/actions/callback/oauth/checks.d.ts.map +1 -0
- package/lib/actions/callback/oauth/checks.js +188 -0
- package/lib/actions/callback/oauth/csrf-token.d.ts +33 -0
- package/lib/actions/callback/oauth/csrf-token.d.ts.map +1 -0
- package/lib/actions/callback/oauth/csrf-token.js +39 -0
- package/lib/actions/index.d.ts +6 -0
- package/lib/actions/index.d.ts.map +1 -0
- package/lib/actions/index.js +5 -0
- package/lib/actions/session.d.ts +5 -0
- package/lib/actions/session.d.ts.map +1 -0
- package/lib/actions/session.js +127 -0
- package/lib/actions/signin/authorization-url.d.ts +12 -0
- package/lib/actions/signin/authorization-url.d.ts.map +1 -0
- package/lib/actions/signin/authorization-url.js +94 -0
- package/lib/actions/signin/index.d.ts +4 -0
- package/lib/actions/signin/index.d.ts.map +1 -0
- package/lib/actions/signin/index.js +22 -0
- package/lib/actions/signin/send-token.d.ts +10 -0
- package/lib/actions/signin/send-token.d.ts.map +1 -0
- package/lib/actions/signin/send-token.js +98 -0
- package/lib/actions/signout.d.ts +11 -0
- package/lib/actions/signout.d.ts.map +1 -0
- package/lib/actions/signout.js +30 -0
- package/lib/actions/webauthn-options.d.ts +8 -0
- package/lib/actions/webauthn-options.d.ts.map +1 -0
- package/lib/actions/webauthn-options.js +60 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +70 -0
- package/lib/init.d.ts +25 -0
- package/lib/init.d.ts.map +1 -0
- package/lib/init.js +172 -0
- package/lib/pages/error.d.ts +17 -0
- package/lib/pages/error.d.ts.map +1 -0
- package/lib/pages/error.js +40 -0
- package/lib/pages/index.d.ts +42 -0
- package/lib/pages/index.d.ts.map +1 -0
- package/lib/pages/index.js +136 -0
- package/lib/pages/signin.d.ts +10 -0
- package/lib/pages/signin.d.ts.map +1 -0
- package/lib/pages/signin.js +75 -0
- package/lib/pages/signout.d.ts +8 -0
- package/lib/pages/signout.d.ts.map +1 -0
- package/lib/pages/signout.js +17 -0
- package/lib/pages/styles.d.ts +3 -0
- package/lib/pages/styles.d.ts.map +1 -0
- package/lib/pages/styles.js +381 -0
- package/lib/pages/verify-request.d.ts +8 -0
- package/lib/pages/verify-request.d.ts.map +1 -0
- package/lib/pages/verify-request.js +11 -0
- package/lib/symbols.d.ts +50 -0
- package/lib/symbols.d.ts.map +1 -0
- package/lib/symbols.js +57 -0
- package/lib/utils/actions.d.ts +3 -0
- package/lib/utils/actions.d.ts.map +1 -0
- package/lib/utils/actions.js +14 -0
- package/lib/utils/assert.d.ts +14 -0
- package/lib/utils/assert.d.ts.map +1 -0
- package/lib/utils/assert.js +168 -0
- package/lib/utils/callback-url.d.ts +17 -0
- package/lib/utils/callback-url.d.ts.map +1 -0
- package/lib/utils/callback-url.js +27 -0
- package/lib/utils/cookie.d.ts +111 -0
- package/lib/utils/cookie.d.ts.map +1 -0
- package/lib/utils/cookie.js +205 -0
- package/lib/utils/date.d.ts +7 -0
- package/lib/utils/date.d.ts.map +1 -0
- package/lib/utils/date.js +8 -0
- package/lib/utils/email.d.ts +20 -0
- package/lib/utils/email.d.ts.map +1 -0
- package/lib/utils/email.js +57 -0
- package/lib/utils/env.d.ts +9 -0
- package/lib/utils/env.d.ts.map +1 -0
- package/lib/utils/env.js +96 -0
- package/lib/utils/logger.d.ts +18 -0
- package/lib/utils/logger.d.ts.map +1 -0
- package/lib/utils/logger.js +50 -0
- package/lib/utils/merge.d.ts +3 -0
- package/lib/utils/merge.d.ts.map +1 -0
- package/lib/utils/merge.js +23 -0
- package/lib/utils/providers.d.ts +19 -0
- package/lib/utils/providers.d.ts.map +1 -0
- package/lib/utils/providers.js +149 -0
- package/lib/utils/session.d.ts +7 -0
- package/lib/utils/session.d.ts.map +1 -0
- package/lib/utils/session.js +29 -0
- package/lib/utils/web.d.ts +10 -0
- package/lib/utils/web.d.ts.map +1 -0
- package/lib/utils/web.js +109 -0
- package/lib/utils/webauthn-client.d.ts +30 -0
- package/lib/utils/webauthn-client.d.ts.map +1 -0
- package/lib/utils/webauthn-client.js +197 -0
- package/lib/utils/webauthn-utils.d.ts +81 -0
- package/lib/utils/webauthn-utils.d.ts.map +1 -0
- package/lib/utils/webauthn-utils.js +343 -0
- package/lib/vendored/cookie.d.ts +120 -0
- package/lib/vendored/cookie.d.ts.map +1 -0
- package/lib/vendored/cookie.js +237 -0
- package/package.json +118 -0
- package/providers/42-school.d.ts +240 -0
- package/providers/42-school.d.ts.map +1 -0
- package/providers/42-school.js +78 -0
- package/providers/apple.d.ts +149 -0
- package/providers/apple.d.ts.map +1 -0
- package/providers/apple.js +104 -0
- package/providers/asgardeo.d.ts +102 -0
- package/providers/asgardeo.d.ts.map +1 -0
- package/providers/asgardeo.js +93 -0
- package/providers/atlassian.d.ts +94 -0
- package/providers/atlassian.d.ts.map +1 -0
- package/providers/atlassian.js +84 -0
- package/providers/auth0.d.ts +116 -0
- package/providers/auth0.d.ts.map +1 -0
- package/providers/auth0.js +49 -0
- package/providers/authentik.d.ts +90 -0
- package/providers/authentik.d.ts.map +1 -0
- package/providers/authentik.js +65 -0
- package/providers/azure-ad-b2c.d.ts +104 -0
- package/providers/azure-ad-b2c.d.ts.map +1 -0
- package/providers/azure-ad-b2c.js +100 -0
- package/providers/azure-ad.d.ts +19 -0
- package/providers/azure-ad.d.ts.map +1 -0
- package/providers/azure-ad.js +23 -0
- package/providers/azure-devops.d.ts +128 -0
- package/providers/azure-devops.d.ts.map +1 -0
- package/providers/azure-devops.js +158 -0
- package/providers/bankid-no.d.ts +134 -0
- package/providers/bankid-no.d.ts.map +1 -0
- package/providers/bankid-no.js +65 -0
- package/providers/battlenet.d.ts +85 -0
- package/providers/battlenet.d.ts.map +1 -0
- package/providers/battlenet.js +81 -0
- package/providers/beyondidentity.d.ts +77 -0
- package/providers/beyondidentity.d.ts.map +1 -0
- package/providers/beyondidentity.js +84 -0
- package/providers/bitbucket.d.ts +89 -0
- package/providers/bitbucket.d.ts.map +1 -0
- package/providers/bitbucket.js +92 -0
- package/providers/box.d.ts +63 -0
- package/providers/box.d.ts.map +1 -0
- package/providers/box.js +73 -0
- package/providers/boxyhq-saml.d.ts +121 -0
- package/providers/boxyhq-saml.d.ts.map +1 -0
- package/providers/boxyhq-saml.js +127 -0
- package/providers/bungie.d.ts +167 -0
- package/providers/bungie.d.ts.map +1 -0
- package/providers/bungie.js +174 -0
- package/providers/click-up.d.ts +75 -0
- package/providers/click-up.d.ts.map +1 -0
- package/providers/click-up.js +89 -0
- package/providers/cognito.d.ts +81 -0
- package/providers/cognito.d.ts.map +1 -0
- package/providers/cognito.js +73 -0
- package/providers/coinbase.d.ts +69 -0
- package/providers/coinbase.d.ts.map +1 -0
- package/providers/coinbase.js +78 -0
- package/providers/concept2.d.ts +81 -0
- package/providers/concept2.d.ts.map +1 -0
- package/providers/concept2.js +86 -0
- package/providers/credentials.d.ts +132 -0
- package/providers/credentials.d.ts.map +1 -0
- package/providers/credentials.js +74 -0
- package/providers/descope.d.ts +91 -0
- package/providers/descope.d.ts.map +1 -0
- package/providers/descope.js +78 -0
- package/providers/discord.d.ts +139 -0
- package/providers/discord.d.ts.map +1 -0
- package/providers/discord.js +86 -0
- package/providers/dribbble.d.ts +88 -0
- package/providers/dribbble.d.ts.map +1 -0
- package/providers/dribbble.js +85 -0
- package/providers/dropbox.d.ts +65 -0
- package/providers/dropbox.d.ts.map +1 -0
- package/providers/dropbox.js +88 -0
- package/providers/duende-identity-server6.d.ts +91 -0
- package/providers/duende-identity-server6.d.ts.map +1 -0
- package/providers/duende-identity-server6.js +80 -0
- package/providers/email.d.ts +41 -0
- package/providers/email.d.ts.map +1 -0
- package/providers/email.js +18 -0
- package/providers/eventbrite.d.ts +78 -0
- package/providers/eventbrite.d.ts.map +1 -0
- package/providers/eventbrite.js +88 -0
- package/providers/eveonline.d.ts +94 -0
- package/providers/eveonline.d.ts.map +1 -0
- package/providers/eveonline.js +92 -0
- package/providers/facebook.d.ts +84 -0
- package/providers/facebook.d.ts.map +1 -0
- package/providers/facebook.js +93 -0
- package/providers/faceit.d.ts +64 -0
- package/providers/faceit.d.ts.map +1 -0
- package/providers/faceit.js +74 -0
- package/providers/figma.d.ts +75 -0
- package/providers/figma.d.ts.map +1 -0
- package/providers/figma.js +81 -0
- package/providers/forwardemail.d.ts +4 -0
- package/providers/forwardemail.d.ts.map +1 -0
- package/providers/forwardemail.js +32 -0
- package/providers/foursquare.d.ts +71 -0
- package/providers/foursquare.d.ts.map +1 -0
- package/providers/foursquare.js +91 -0
- package/providers/freshbooks.d.ts +66 -0
- package/providers/freshbooks.d.ts.map +1 -0
- package/providers/freshbooks.js +76 -0
- package/providers/frontegg.d.ts +95 -0
- package/providers/frontegg.d.ts.map +1 -0
- package/providers/frontegg.js +88 -0
- package/providers/fusionauth.d.ts +279 -0
- package/providers/fusionauth.d.ts.map +1 -0
- package/providers/fusionauth.js +292 -0
- package/providers/github.d.ts +127 -0
- package/providers/github.d.ts.map +1 -0
- package/providers/github.js +115 -0
- package/providers/gitlab.d.ts +115 -0
- package/providers/gitlab.d.ts.map +1 -0
- package/providers/gitlab.js +75 -0
- package/providers/google.d.ts +138 -0
- package/providers/google.d.ts.map +1 -0
- package/providers/google.js +119 -0
- package/providers/hubspot.d.ts +76 -0
- package/providers/hubspot.d.ts.map +1 -0
- package/providers/hubspot.js +93 -0
- package/providers/huggingface.d.ts +216 -0
- package/providers/huggingface.d.ts.map +1 -0
- package/providers/huggingface.js +101 -0
- package/providers/identity-server4.d.ts +69 -0
- package/providers/identity-server4.d.ts.map +1 -0
- package/providers/identity-server4.js +64 -0
- package/providers/index.d.ts +61 -0
- package/providers/index.d.ts.map +1 -0
- package/providers/index.js +3 -0
- package/providers/instagram.d.ts +74 -0
- package/providers/instagram.d.ts.map +1 -0
- package/providers/instagram.js +87 -0
- package/providers/kakao.d.ts +148 -0
- package/providers/kakao.d.ts.map +1 -0
- package/providers/kakao.js +103 -0
- package/providers/keycloak.d.ts +100 -0
- package/providers/keycloak.d.ts.map +1 -0
- package/providers/keycloak.js +73 -0
- package/providers/kinde.d.ts +73 -0
- package/providers/kinde.d.ts.map +1 -0
- package/providers/kinde.js +51 -0
- package/providers/line.d.ts +83 -0
- package/providers/line.d.ts.map +1 -0
- package/providers/line.js +73 -0
- package/providers/linkedin.d.ts +77 -0
- package/providers/linkedin.d.ts.map +1 -0
- package/providers/linkedin.js +65 -0
- package/providers/logto.d.ts +98 -0
- package/providers/logto.d.ts.map +1 -0
- package/providers/logto.js +81 -0
- package/providers/loops.d.ts +40 -0
- package/providers/loops.d.ts.map +1 -0
- package/providers/loops.js +59 -0
- package/providers/mailchimp.d.ts +66 -0
- package/providers/mailchimp.d.ts.map +1 -0
- package/providers/mailchimp.js +76 -0
- package/providers/mailgun.d.ts +55 -0
- package/providers/mailgun.d.ts.map +1 -0
- package/providers/mailgun.js +74 -0
- package/providers/mailru.d.ts +63 -0
- package/providers/mailru.d.ts.map +1 -0
- package/providers/mailru.js +61 -0
- package/providers/mastodon.d.ts +90 -0
- package/providers/mastodon.d.ts.map +1 -0
- package/providers/mastodon.js +75 -0
- package/providers/mattermost.d.ts +132 -0
- package/providers/mattermost.d.ts.map +1 -0
- package/providers/mattermost.js +83 -0
- package/providers/medium.d.ts +68 -0
- package/providers/medium.d.ts.map +1 -0
- package/providers/medium.js +84 -0
- package/providers/microsoft-entra-id.d.ts +428 -0
- package/providers/microsoft-entra-id.d.ts.map +1 -0
- package/providers/microsoft-entra-id.js +156 -0
- package/providers/naver.d.ts +80 -0
- package/providers/naver.d.ts.map +1 -0
- package/providers/naver.js +79 -0
- package/providers/netlify.d.ts +66 -0
- package/providers/netlify.d.ts.map +1 -0
- package/providers/netlify.js +85 -0
- package/providers/netsuite.d.ts +189 -0
- package/providers/netsuite.d.ts.map +1 -0
- package/providers/netsuite.js +170 -0
- package/providers/nextcloud.d.ts +150 -0
- package/providers/nextcloud.d.ts.map +1 -0
- package/providers/nextcloud.js +99 -0
- package/providers/nodemailer.d.ts +27 -0
- package/providers/nodemailer.d.ts.map +1 -0
- package/providers/nodemailer.js +34 -0
- package/providers/notion.d.ts +99 -0
- package/providers/notion.d.ts.map +1 -0
- package/providers/notion.js +110 -0
- package/providers/oauth.d.ts +188 -0
- package/providers/oauth.d.ts.map +1 -0
- package/providers/oauth.js +1 -0
- package/providers/okta.d.ts +99 -0
- package/providers/okta.d.ts.map +1 -0
- package/providers/okta.js +63 -0
- package/providers/onelogin.d.ts +65 -0
- package/providers/onelogin.d.ts.map +1 -0
- package/providers/onelogin.js +61 -0
- package/providers/ory-hydra.d.ts +79 -0
- package/providers/ory-hydra.d.ts.map +1 -0
- package/providers/ory-hydra.js +67 -0
- package/providers/osso.d.ts +79 -0
- package/providers/osso.d.ts.map +1 -0
- package/providers/osso.js +77 -0
- package/providers/osu.d.ts +116 -0
- package/providers/osu.d.ts.map +1 -0
- package/providers/osu.js +75 -0
- package/providers/passage.d.ts +88 -0
- package/providers/passage.d.ts.map +1 -0
- package/providers/passage.js +75 -0
- package/providers/passkey.d.ts +65 -0
- package/providers/passkey.d.ts.map +1 -0
- package/providers/passkey.js +87 -0
- package/providers/patreon.d.ts +73 -0
- package/providers/patreon.d.ts.map +1 -0
- package/providers/patreon.js +77 -0
- package/providers/ping-id.d.ts +57 -0
- package/providers/ping-id.d.ts.map +1 -0
- package/providers/ping-id.js +40 -0
- package/providers/pinterest.d.ts +79 -0
- package/providers/pinterest.d.ts.map +1 -0
- package/providers/pinterest.js +85 -0
- package/providers/pipedrive.d.ts +99 -0
- package/providers/pipedrive.d.ts.map +1 -0
- package/providers/pipedrive.js +71 -0
- package/providers/postmark.d.ts +4 -0
- package/providers/postmark.d.ts.map +1 -0
- package/providers/postmark.js +36 -0
- package/providers/provider-types.d.ts +3 -0
- package/providers/provider-types.d.ts.map +1 -0
- package/providers/provider-types.js +1 -0
- package/providers/reddit.d.ts +88 -0
- package/providers/reddit.d.ts.map +1 -0
- package/providers/reddit.js +90 -0
- package/providers/resend.d.ts +4 -0
- package/providers/resend.d.ts.map +1 -0
- package/providers/resend.js +32 -0
- package/providers/roblox.d.ts +67 -0
- package/providers/roblox.d.ts.map +1 -0
- package/providers/roblox.js +53 -0
- package/providers/salesforce.d.ts +59 -0
- package/providers/salesforce.d.ts.map +1 -0
- package/providers/salesforce.js +52 -0
- package/providers/sendgrid.d.ts +4 -0
- package/providers/sendgrid.d.ts.map +1 -0
- package/providers/sendgrid.js +35 -0
- package/providers/simplelogin.d.ts +87 -0
- package/providers/simplelogin.d.ts.map +1 -0
- package/providers/simplelogin.js +83 -0
- package/providers/slack.d.ts +102 -0
- package/providers/slack.d.ts.map +1 -0
- package/providers/slack.js +69 -0
- package/providers/spotify.d.ts +75 -0
- package/providers/spotify.d.ts.map +1 -0
- package/providers/spotify.js +73 -0
- package/providers/strava.d.ts +68 -0
- package/providers/strava.d.ts.map +1 -0
- package/providers/strava.js +80 -0
- package/providers/threads.d.ts +108 -0
- package/providers/threads.d.ts.map +1 -0
- package/providers/threads.js +89 -0
- package/providers/tiktok.d.ts +248 -0
- package/providers/tiktok.d.ts.map +1 -0
- package/providers/tiktok.js +195 -0
- package/providers/todoist.d.ts +76 -0
- package/providers/todoist.d.ts.map +1 -0
- package/providers/todoist.js +97 -0
- package/providers/trakt.d.ts +93 -0
- package/providers/trakt.d.ts.map +1 -0
- package/providers/trakt.js +91 -0
- package/providers/twitch.d.ts +71 -0
- package/providers/twitch.d.ts.map +1 -0
- package/providers/twitch.js +96 -0
- package/providers/twitter.d.ts +183 -0
- package/providers/twitter.d.ts.map +1 -0
- package/providers/twitter.js +100 -0
- package/providers/united-effects.d.ts +80 -0
- package/providers/united-effects.d.ts.map +1 -0
- package/providers/united-effects.js +72 -0
- package/providers/vipps.d.ts +71 -0
- package/providers/vipps.d.ts.map +1 -0
- package/providers/vipps.js +33 -0
- package/providers/vk.d.ts +334 -0
- package/providers/vk.d.ts.map +1 -0
- package/providers/vk.js +103 -0
- package/providers/webauthn.d.ts +148 -0
- package/providers/webauthn.d.ts.map +1 -0
- package/providers/webauthn.js +128 -0
- package/providers/webex.d.ts +78 -0
- package/providers/webex.d.ts.map +1 -0
- package/providers/webex.js +73 -0
- package/providers/wechat.d.ts +78 -0
- package/providers/wechat.d.ts.map +1 -0
- package/providers/wechat.js +105 -0
- package/providers/wikimedia.d.ts +99 -0
- package/providers/wikimedia.d.ts.map +1 -0
- package/providers/wikimedia.js +90 -0
- package/providers/wordpress.d.ts +65 -0
- package/providers/wordpress.d.ts.map +1 -0
- package/providers/wordpress.js +71 -0
- package/providers/workos.d.ts +154 -0
- package/providers/workos.d.ts.map +1 -0
- package/providers/workos.js +143 -0
- package/providers/yandex.d.ts +131 -0
- package/providers/yandex.d.ts.map +1 -0
- package/providers/yandex.js +80 -0
- package/providers/zitadel.d.ts +117 -0
- package/providers/zitadel.d.ts.map +1 -0
- package/providers/zitadel.js +95 -0
- package/providers/zoho.d.ts +63 -0
- package/providers/zoho.d.ts.map +1 -0
- package/providers/zoho.js +79 -0
- package/providers/zoom.d.ts +93 -0
- package/providers/zoom.d.ts.map +1 -0
- package/providers/zoom.js +82 -0
- package/src/adapters/server-actions-helpers.ts +126 -0
- package/src/adapters.ts +603 -0
- package/src/errors.ts +551 -0
- package/src/index.ts +689 -0
- package/src/jwt.ts +283 -0
- package/src/lib/actions/callback/handle-login.ts +334 -0
- package/src/lib/actions/callback/index.ts +554 -0
- package/src/lib/actions/callback/oauth/callback.ts +347 -0
- package/src/lib/actions/callback/oauth/checks.ts +258 -0
- package/src/lib/actions/callback/oauth/csrf-token.ts +60 -0
- package/src/lib/actions/index.ts +5 -0
- package/src/lib/actions/session.ts +167 -0
- package/src/lib/actions/signin/authorization-url.ts +123 -0
- package/src/lib/actions/signin/index.ts +37 -0
- package/src/lib/actions/signin/send-token.ts +124 -0
- package/src/lib/actions/signout.ts +38 -0
- package/src/lib/actions/webauthn-options.ts +100 -0
- package/src/lib/index.ts +97 -0
- package/src/lib/init.ts +236 -0
- package/src/lib/pages/error.tsx +106 -0
- package/src/lib/pages/index.ts +181 -0
- package/src/lib/pages/signin.tsx +255 -0
- package/src/lib/pages/signout.tsx +49 -0
- package/src/lib/pages/styles.css +377 -0
- package/src/lib/pages/styles.ts +381 -0
- package/src/lib/pages/verify-request.tsx +36 -0
- package/src/lib/symbols.ts +60 -0
- package/src/lib/utils/actions.ts +17 -0
- package/src/lib/utils/assert.ts +259 -0
- package/src/lib/utils/callback-url.ts +42 -0
- package/src/lib/utils/cookie.ts +248 -0
- package/src/lib/utils/date.ts +8 -0
- package/src/lib/utils/email.ts +65 -0
- package/src/lib/utils/env.ts +113 -0
- package/src/lib/utils/logger.ts +75 -0
- package/src/lib/utils/merge.ts +30 -0
- package/src/lib/utils/providers.ts +203 -0
- package/src/lib/utils/session.ts +41 -0
- package/src/lib/utils/web.ts +151 -0
- package/src/lib/utils/webauthn-client.js +229 -0
- package/src/lib/utils/webauthn-utils.ts +531 -0
- package/src/lib/vendored/cookie.ts +383 -0
- package/src/providers/42-school.ts +256 -0
- package/src/providers/apple.ts +206 -0
- package/src/providers/asgardeo.ts +118 -0
- package/src/providers/atlassian.ts +120 -0
- package/src/providers/auth0.ts +127 -0
- package/src/providers/authentik.ts +100 -0
- package/src/providers/azure-ad-b2c.ts +124 -0
- package/src/providers/azure-ad.ts +30 -0
- package/src/providers/azure-devops.ts +184 -0
- package/src/providers/bankid-no.ts +161 -0
- package/src/providers/battlenet.ts +107 -0
- package/src/providers/beyondidentity.ts +102 -0
- package/src/providers/bitbucket.ts +122 -0
- package/src/providers/box.ts +87 -0
- package/src/providers/boxyhq-saml.ts +148 -0
- package/src/providers/bungie.ts +192 -0
- package/src/providers/click-up.ts +104 -0
- package/src/providers/cognito.ts +94 -0
- package/src/providers/coinbase.ts +93 -0
- package/src/providers/concept2.ts +108 -0
- package/src/providers/credentials.ts +157 -0
- package/src/providers/descope.ts +105 -0
- package/src/providers/discord.ts +176 -0
- package/src/providers/dribbble.ts +122 -0
- package/src/providers/dropbox.ts +102 -0
- package/src/providers/duende-identity-server6.ts +101 -0
- package/src/providers/email.ts +60 -0
- package/src/providers/eventbrite.ts +105 -0
- package/src/providers/eveonline.ts +117 -0
- package/src/providers/facebook.ts +119 -0
- package/src/providers/faceit.ts +90 -0
- package/src/providers/figma.ts +105 -0
- package/src/providers/forwardemail.ts +37 -0
- package/src/providers/foursquare.ts +105 -0
- package/src/providers/freshbooks.ts +90 -0
- package/src/providers/frontegg.ts +111 -0
- package/src/providers/fusionauth.ts +336 -0
- package/src/providers/github.ts +187 -0
- package/src/providers/gitlab.ts +140 -0
- package/src/providers/google.ts +152 -0
- package/src/providers/hubspot.ts +117 -0
- package/src/providers/huggingface.ts +234 -0
- package/src/providers/identity-server4.ts +78 -0
- package/src/providers/index.ts +115 -0
- package/src/providers/instagram.ts +103 -0
- package/src/providers/kakao.ts +184 -0
- package/src/providers/keycloak.ts +111 -0
- package/src/providers/kinde.ts +85 -0
- package/src/providers/line.ts +99 -0
- package/src/providers/linkedin.ts +91 -0
- package/src/providers/logto.ts +122 -0
- package/src/providers/loops.ts +79 -0
- package/src/providers/mailchimp.ts +90 -0
- package/src/providers/mailgun.ts +98 -0
- package/src/providers/mailru.ts +75 -0
- package/src/providers/mastodon.ts +112 -0
- package/src/providers/mattermost.ts +154 -0
- package/src/providers/medium.ts +89 -0
- package/src/providers/microsoft-entra-id.ts +497 -0
- package/src/providers/naver.ts +102 -0
- package/src/providers/netlify.ts +90 -0
- package/src/providers/netsuite.ts +225 -0
- package/src/providers/nextcloud.ts +207 -0
- package/src/providers/nodemailer.ts +84 -0
- package/src/providers/notion.ts +166 -0
- package/src/providers/oauth.ts +310 -0
- package/src/providers/okta.ts +111 -0
- package/src/providers/onelogin.ts +75 -0
- package/src/providers/ory-hydra.ts +93 -0
- package/src/providers/osso.ts +91 -0
- package/src/providers/osu.ts +138 -0
- package/src/providers/passage.ts +103 -0
- package/src/providers/passkey.ts +94 -0
- package/src/providers/patreon.ts +98 -0
- package/src/providers/ping-id.ts +68 -0
- package/src/providers/pinterest.ts +106 -0
- package/src/providers/pipedrive.ts +120 -0
- package/src/providers/postmark.ts +38 -0
- package/src/providers/provider-types.ts +107 -0
- package/src/providers/reddit.ts +104 -0
- package/src/providers/resend.ts +35 -0
- package/src/providers/roblox.ts +94 -0
- package/src/providers/salesforce.ts +73 -0
- package/src/providers/sendgrid.ts +36 -0
- package/src/providers/simplelogin.ts +107 -0
- package/src/providers/slack.ts +115 -0
- package/src/providers/spotify.ts +99 -0
- package/src/providers/strava.ts +101 -0
- package/src/providers/threads.ts +135 -0
- package/src/providers/tiktok.ts +319 -0
- package/src/providers/todoist.ts +122 -0
- package/src/providers/trakt.ts +120 -0
- package/src/providers/twitch.ts +121 -0
- package/src/providers/twitter.ts +207 -0
- package/src/providers/united-effects.ts +89 -0
- package/src/providers/vipps.ts +86 -0
- package/src/providers/vk.ts +401 -0
- package/src/providers/webauthn.ts +296 -0
- package/src/providers/webex.ts +102 -0
- package/src/providers/wechat.ts +141 -0
- package/src/providers/wikimedia.ts +258 -0
- package/src/providers/wordpress.ts +86 -0
- package/src/providers/workos.ts +180 -0
- package/src/providers/yandex.ts +159 -0
- package/src/providers/zitadel.ts +128 -0
- package/src/providers/zoho.ts +84 -0
- package/src/providers/zoom.ts +119 -0
- package/src/types.ts +430 -0
- package/src/warnings.ts +21 -0
- package/types.d.ts +309 -0
- package/types.d.ts.map +1 -0
- package/types.js +53 -0
- package/warnings.d.ts +17 -0
- package/warnings.d.ts.map +1 -0
- package/warnings.js +1 -0
package/src/jwt.ts
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*
|
|
4
|
+
* This module contains functions and types
|
|
5
|
+
* to encode and decode {@link https://authjs.dev/concepts/session-strategies#jwt-session JWT}s
|
|
6
|
+
* issued and used by Auth.js.
|
|
7
|
+
*
|
|
8
|
+
* The JWT issued by Auth.js is _encrypted by default_, using the _A256CBC-HS512_ algorithm ({@link https://www.rfc-editor.org/rfc/rfc7518.html#section-5.2.5 JWE}).
|
|
9
|
+
* It uses the `AUTH_SECRET` environment variable or the passed `secret` property to derive a suitable encryption key.
|
|
10
|
+
*
|
|
11
|
+
* :::info Note
|
|
12
|
+
* Auth.js JWTs are meant to be used by the same app that issued them.
|
|
13
|
+
* If you need JWT authentication for your third-party API, you should rely on your Identity Provider instead.
|
|
14
|
+
* :::
|
|
15
|
+
*
|
|
16
|
+
* ## Installation
|
|
17
|
+
*
|
|
18
|
+
* ```bash npm2yarn
|
|
19
|
+
* npm install @auth/core
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* You can then import this submodule from `@auth/core/jwt`.
|
|
23
|
+
*
|
|
24
|
+
* ## Usage
|
|
25
|
+
*
|
|
26
|
+
* :::warning Warning
|
|
27
|
+
* This module *will* be refactored/changed. We do not recommend relying on it right now.
|
|
28
|
+
* :::
|
|
29
|
+
*
|
|
30
|
+
*
|
|
31
|
+
* ## Resources
|
|
32
|
+
*
|
|
33
|
+
* - [What is a JWT session strategy](https://authjs.dev/concepts/session-strategies#jwt-session)
|
|
34
|
+
* - [RFC7519 - JSON Web Token (JWT)](https://www.rfc-editor.org/rfc/rfc7519)
|
|
35
|
+
*
|
|
36
|
+
* @module jwt
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import { hkdf } from "@panva/hkdf"
|
|
40
|
+
import { EncryptJWT, base64url, calculateJwkThumbprint, jwtDecrypt } from "jose"
|
|
41
|
+
import { defaultCookies, SessionStore } from "./lib/utils/cookie.js"
|
|
42
|
+
import { Awaitable } from "./types.js"
|
|
43
|
+
import type { LoggerInstance } from "./lib/utils/logger.js"
|
|
44
|
+
import { MissingSecret } from "./errors.js"
|
|
45
|
+
import * as cookie from "./lib/vendored/cookie.js"
|
|
46
|
+
|
|
47
|
+
const { parse: parseCookie } = cookie
|
|
48
|
+
const DEFAULT_MAX_AGE = 30 * 24 * 60 * 60 // 30 days
|
|
49
|
+
|
|
50
|
+
const now = () => (Date.now() / 1000) | 0
|
|
51
|
+
|
|
52
|
+
const alg = "dir"
|
|
53
|
+
const enc = "A256CBC-HS512"
|
|
54
|
+
type Digest = Parameters<typeof calculateJwkThumbprint>[1]
|
|
55
|
+
|
|
56
|
+
/** Issues a JWT. By default, the JWT is encrypted using "A256CBC-HS512". */
|
|
57
|
+
export async function encode<Payload = JWT>(params: JWTEncodeParams<Payload>) {
|
|
58
|
+
const { token = {}, secret, maxAge = DEFAULT_MAX_AGE, salt } = params
|
|
59
|
+
const secrets = Array.isArray(secret) ? secret : [secret]
|
|
60
|
+
const encryptionSecret = await getDerivedEncryptionKey(enc, secrets[0], salt)
|
|
61
|
+
|
|
62
|
+
const thumbprint = await calculateJwkThumbprint(
|
|
63
|
+
{ kty: "oct", k: base64url.encode(encryptionSecret) },
|
|
64
|
+
`sha${encryptionSecret.byteLength << 3}` as Digest
|
|
65
|
+
)
|
|
66
|
+
// @ts-expect-error `jose` allows any object as payload.
|
|
67
|
+
return await new EncryptJWT(token)
|
|
68
|
+
.setProtectedHeader({ alg, enc, kid: thumbprint })
|
|
69
|
+
.setIssuedAt()
|
|
70
|
+
.setExpirationTime(now() + maxAge)
|
|
71
|
+
.setJti(crypto.randomUUID())
|
|
72
|
+
.encrypt(encryptionSecret)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Decodes an Auth.js issued JWT. */
|
|
76
|
+
export async function decode<Payload = JWT>(
|
|
77
|
+
params: JWTDecodeParams
|
|
78
|
+
): Promise<Payload | null> {
|
|
79
|
+
const { token, secret, salt } = params
|
|
80
|
+
const secrets = Array.isArray(secret) ? secret : [secret]
|
|
81
|
+
if (!token) return null
|
|
82
|
+
const { payload } = await jwtDecrypt(
|
|
83
|
+
token,
|
|
84
|
+
async ({ kid, enc }) => {
|
|
85
|
+
for (const secret of secrets) {
|
|
86
|
+
const encryptionSecret = await getDerivedEncryptionKey(
|
|
87
|
+
enc,
|
|
88
|
+
secret,
|
|
89
|
+
salt
|
|
90
|
+
)
|
|
91
|
+
if (kid === undefined) return encryptionSecret
|
|
92
|
+
|
|
93
|
+
const thumbprint = await calculateJwkThumbprint(
|
|
94
|
+
{ kty: "oct", k: base64url.encode(encryptionSecret) },
|
|
95
|
+
`sha${encryptionSecret.byteLength << 3}` as Digest
|
|
96
|
+
)
|
|
97
|
+
if (kid === thumbprint) return encryptionSecret
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new Error("no matching decryption secret")
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
clockTolerance: 15,
|
|
104
|
+
keyManagementAlgorithms: [alg],
|
|
105
|
+
contentEncryptionAlgorithms: [enc, "A256GCM"],
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
return payload as Payload
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
type GetTokenParamsBase = {
|
|
112
|
+
secret?: JWTDecodeParams["secret"]
|
|
113
|
+
salt?: JWTDecodeParams["salt"]
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface GetTokenParams<R extends boolean = false>
|
|
117
|
+
extends GetTokenParamsBase {
|
|
118
|
+
/** The request containing the JWT either in the cookies or in the `Authorization` header. */
|
|
119
|
+
req: Request | { headers: Headers | Record<string, string> }
|
|
120
|
+
/**
|
|
121
|
+
* Use secure prefix for cookie name, unless URL in `NEXTAUTH_URL` is http://
|
|
122
|
+
* or not set (e.g. development or test instance) case use unprefixed name
|
|
123
|
+
*/
|
|
124
|
+
secureCookie?: boolean
|
|
125
|
+
/** If the JWT is in the cookie, what name `getToken()` should look for. */
|
|
126
|
+
cookieName?: string
|
|
127
|
+
/**
|
|
128
|
+
* `getToken()` will return the raw JWT if this is set to `true`
|
|
129
|
+
*
|
|
130
|
+
* @default false
|
|
131
|
+
*/
|
|
132
|
+
raw?: R
|
|
133
|
+
decode?: JWTOptions["decode"]
|
|
134
|
+
logger?: LoggerInstance | Console
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Takes an Auth.js request (`req`) and returns either the Auth.js issued JWT's payload,
|
|
139
|
+
* or the raw JWT string. We look for the JWT in the either the cookies, or the `Authorization` header.
|
|
140
|
+
*/
|
|
141
|
+
export async function getToken<R extends boolean = false>(
|
|
142
|
+
params: GetTokenParams<R>
|
|
143
|
+
): Promise<R extends true ? string : JWT | null>
|
|
144
|
+
export async function getToken(
|
|
145
|
+
params: GetTokenParams
|
|
146
|
+
): Promise<string | JWT | null> {
|
|
147
|
+
const {
|
|
148
|
+
secureCookie,
|
|
149
|
+
cookieName = defaultCookies(secureCookie ?? false).sessionToken.name,
|
|
150
|
+
decode: _decode = decode,
|
|
151
|
+
salt = cookieName,
|
|
152
|
+
secret,
|
|
153
|
+
logger = console,
|
|
154
|
+
raw,
|
|
155
|
+
req,
|
|
156
|
+
} = params
|
|
157
|
+
|
|
158
|
+
if (!req) throw new Error("Must pass `req` to JWT getToken()")
|
|
159
|
+
|
|
160
|
+
const headers =
|
|
161
|
+
req.headers instanceof Headers ? req.headers : new Headers(req.headers)
|
|
162
|
+
|
|
163
|
+
const sessionStore = new SessionStore(
|
|
164
|
+
{ name: cookieName, options: { secure: secureCookie } },
|
|
165
|
+
parseCookie(headers.get("cookie") ?? ""),
|
|
166
|
+
logger
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
let token = sessionStore.value
|
|
170
|
+
|
|
171
|
+
const authorizationHeader = headers.get("authorization")
|
|
172
|
+
|
|
173
|
+
if (!token && authorizationHeader?.split(" ")[0] === "Bearer") {
|
|
174
|
+
const urlEncodedToken = authorizationHeader.split(" ")[1]
|
|
175
|
+
token = decodeURIComponent(urlEncodedToken)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!token) return null
|
|
179
|
+
|
|
180
|
+
if (raw) return token
|
|
181
|
+
|
|
182
|
+
if (!secret)
|
|
183
|
+
throw new MissingSecret("Must pass `secret` if not set to JWT getToken()")
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
return await _decode({ token, secret, salt })
|
|
187
|
+
} catch {
|
|
188
|
+
return null
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function getDerivedEncryptionKey(
|
|
193
|
+
enc: string,
|
|
194
|
+
keyMaterial: Parameters<typeof hkdf>[1],
|
|
195
|
+
salt: Parameters<typeof hkdf>[2]
|
|
196
|
+
) {
|
|
197
|
+
let length: number
|
|
198
|
+
switch (enc) {
|
|
199
|
+
case "A256CBC-HS512":
|
|
200
|
+
length = 64
|
|
201
|
+
break
|
|
202
|
+
case "A256GCM":
|
|
203
|
+
length = 32
|
|
204
|
+
break
|
|
205
|
+
default:
|
|
206
|
+
throw new Error("Unsupported JWT Content Encryption Algorithm")
|
|
207
|
+
}
|
|
208
|
+
return await hkdf(
|
|
209
|
+
"sha256",
|
|
210
|
+
keyMaterial,
|
|
211
|
+
salt,
|
|
212
|
+
`Auth.js Generated Encryption Key (${salt})`,
|
|
213
|
+
length
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface DefaultJWT extends Record<string, unknown> {
|
|
218
|
+
name?: string | null
|
|
219
|
+
email?: string | null
|
|
220
|
+
picture?: string | null
|
|
221
|
+
sub?: string
|
|
222
|
+
iat?: number
|
|
223
|
+
exp?: number
|
|
224
|
+
jti?: string
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Returned by the `jwt` callback when using JWT sessions
|
|
229
|
+
*
|
|
230
|
+
* [`jwt` callback](https://authjs.dev/reference/core/types#jwt)
|
|
231
|
+
*/
|
|
232
|
+
export interface JWT extends Record<string, unknown>, DefaultJWT {}
|
|
233
|
+
|
|
234
|
+
export interface JWTEncodeParams<Payload = JWT> {
|
|
235
|
+
/**
|
|
236
|
+
* The maximum age of the Auth.js issued JWT in seconds.
|
|
237
|
+
*
|
|
238
|
+
* @default 30 * 24 * 60 * 60 // 30 days
|
|
239
|
+
*/
|
|
240
|
+
maxAge?: number
|
|
241
|
+
/** Used in combination with `secret`, to derive the encryption secret for JWTs. */
|
|
242
|
+
salt: string
|
|
243
|
+
/** Used in combination with `salt`, to derive the encryption secret for JWTs. */
|
|
244
|
+
secret: string | string[]
|
|
245
|
+
/** The JWT payload. */
|
|
246
|
+
token?: Payload
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface JWTDecodeParams {
|
|
250
|
+
/** Used in combination with `secret`, to derive the encryption secret for JWTs. */
|
|
251
|
+
salt: string
|
|
252
|
+
/**
|
|
253
|
+
* Used in combination with `salt`, to derive the encryption secret for JWTs.
|
|
254
|
+
*
|
|
255
|
+
* @note
|
|
256
|
+
* You can also pass an array of secrets, in which case the first secret that successfully
|
|
257
|
+
* decrypts the JWT will be used. This is useful for rotating secrets without invalidating existing sessions.
|
|
258
|
+
* The newer secret should be added to the start of the array, which will be used for all new sessions.
|
|
259
|
+
*/
|
|
260
|
+
secret: string | string[]
|
|
261
|
+
/** The Auth.js issued JWT to be decoded */
|
|
262
|
+
token?: string
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface JWTOptions {
|
|
266
|
+
/**
|
|
267
|
+
* The secret used to encode/decode the Auth.js issued JWT.
|
|
268
|
+
* It can be an array of secrets, in which case the first secret that successfully
|
|
269
|
+
* decrypts the JWT will be used. This is useful for rotating secrets without invalidating existing sessions.
|
|
270
|
+
* @internal
|
|
271
|
+
*/
|
|
272
|
+
secret: string | string[]
|
|
273
|
+
/**
|
|
274
|
+
* The maximum age of the Auth.js issued JWT in seconds.
|
|
275
|
+
*
|
|
276
|
+
* @default 30 * 24 * 60 * 60 // 30 days
|
|
277
|
+
*/
|
|
278
|
+
maxAge: number
|
|
279
|
+
/** Override this method to control the Auth.js issued JWT encoding. */
|
|
280
|
+
encode: (params: JWTEncodeParams) => Awaitable<string>
|
|
281
|
+
/** Override this method to control the Auth.js issued JWT decoding. */
|
|
282
|
+
decode: (params: JWTDecodeParams) => Awaitable<JWT | null>
|
|
283
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { AccountNotLinked, OAuthAccountNotLinked } from "../../../errors.js"
|
|
2
|
+
import { fromDate } from "../../utils/date.js"
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
AdapterAccount,
|
|
6
|
+
AdapterSession,
|
|
7
|
+
AdapterUser,
|
|
8
|
+
} from "../../../adapters.js"
|
|
9
|
+
import type { Account, InternalOptions, User } from "../../../types.js"
|
|
10
|
+
import type { JWT } from "../../../jwt.js"
|
|
11
|
+
import type { OAuthConfig } from "../../../providers/index.js"
|
|
12
|
+
import type { SessionToken } from "../../utils/cookie.js"
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* This function handles the complex flow of signing users in, and either creating,
|
|
16
|
+
* linking (or not linking) accounts depending on if the user is currently logged
|
|
17
|
+
* in, if they have account already and the authentication mechanism they are using.
|
|
18
|
+
*
|
|
19
|
+
* It prevents insecure behaviour, such as linking OAuth accounts unless a user is
|
|
20
|
+
* signed in and authenticated with an existing valid account.
|
|
21
|
+
*
|
|
22
|
+
* All verification (e.g. OAuth flows or email address verification flows) are
|
|
23
|
+
* done prior to this handler being called to avoid additional complexity in this
|
|
24
|
+
* handler.
|
|
25
|
+
*/
|
|
26
|
+
export async function handleLoginOrRegister(
|
|
27
|
+
sessionToken: SessionToken,
|
|
28
|
+
_profile: User | AdapterUser | { email: string },
|
|
29
|
+
_account: AdapterAccount | Account | null,
|
|
30
|
+
options: InternalOptions
|
|
31
|
+
) {
|
|
32
|
+
// Input validation
|
|
33
|
+
if (!_account?.providerAccountId || !_account.type)
|
|
34
|
+
throw new Error("Missing or invalid provider account")
|
|
35
|
+
if (!["email", "oauth", "oidc", "webauthn"].includes(_account.type))
|
|
36
|
+
throw new Error("Provider not supported")
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
adapter,
|
|
40
|
+
jwt,
|
|
41
|
+
events,
|
|
42
|
+
session: { strategy: sessionStrategy, generateSessionToken },
|
|
43
|
+
} = options
|
|
44
|
+
|
|
45
|
+
// If no adapter is configured then we don't have a database and cannot
|
|
46
|
+
// persist data; in this mode we just return a dummy session object.
|
|
47
|
+
if (!adapter) {
|
|
48
|
+
return { user: _profile as User, account: _account as Account }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const profile = _profile as AdapterUser
|
|
52
|
+
let account = _account as AdapterAccount
|
|
53
|
+
|
|
54
|
+
const {
|
|
55
|
+
createUser,
|
|
56
|
+
updateUser,
|
|
57
|
+
getUser,
|
|
58
|
+
getUserByAccount,
|
|
59
|
+
getUserByEmail,
|
|
60
|
+
linkAccount,
|
|
61
|
+
createSession,
|
|
62
|
+
getSessionAndUser,
|
|
63
|
+
deleteSession,
|
|
64
|
+
} = adapter
|
|
65
|
+
|
|
66
|
+
let session: AdapterSession | JWT | null = null
|
|
67
|
+
let user: AdapterUser | null = null
|
|
68
|
+
let isNewUser = false
|
|
69
|
+
|
|
70
|
+
const useJwtSession = sessionStrategy === "jwt"
|
|
71
|
+
|
|
72
|
+
if (sessionToken) {
|
|
73
|
+
if (useJwtSession) {
|
|
74
|
+
try {
|
|
75
|
+
const salt = options.cookies.sessionToken.name
|
|
76
|
+
session = await jwt.decode({ ...jwt, token: sessionToken, salt })
|
|
77
|
+
if (session && "sub" in session && session.sub) {
|
|
78
|
+
user = await getUser(session.sub)
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
// If session can't be verified, treat as no session
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
const userAndSession = await getSessionAndUser(sessionToken)
|
|
85
|
+
if (userAndSession) {
|
|
86
|
+
session = userAndSession.session
|
|
87
|
+
user = userAndSession.user
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (account.type === "email") {
|
|
93
|
+
// If signing in with an email, check if an account with the same email address exists already
|
|
94
|
+
const userByEmail = await getUserByEmail(profile.email)
|
|
95
|
+
if (userByEmail) {
|
|
96
|
+
// If they are not already signed in as the same user, this flow will
|
|
97
|
+
// sign them out of the current session and sign them in as the new user
|
|
98
|
+
if (user?.id !== userByEmail.id && !useJwtSession && sessionToken) {
|
|
99
|
+
// Delete existing session if they are currently signed in as another user.
|
|
100
|
+
// This will switch user accounts for the session in cases where the user was
|
|
101
|
+
// already logged in with a different account.
|
|
102
|
+
await deleteSession(sessionToken)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Update emailVerified property on the user object
|
|
106
|
+
user = await updateUser({
|
|
107
|
+
id: userByEmail.id,
|
|
108
|
+
emailVerified: new Date(),
|
|
109
|
+
})
|
|
110
|
+
await events.updateUser?.({ user })
|
|
111
|
+
} else {
|
|
112
|
+
// Create user account if there isn't one for the email address already
|
|
113
|
+
user = await createUser({ ...profile, emailVerified: new Date() })
|
|
114
|
+
await events.createUser?.({ user })
|
|
115
|
+
isNewUser = true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Create new session
|
|
119
|
+
session = useJwtSession
|
|
120
|
+
? {}
|
|
121
|
+
: await createSession({
|
|
122
|
+
sessionToken: generateSessionToken(),
|
|
123
|
+
userId: user.id,
|
|
124
|
+
expires: fromDate(options.session.maxAge),
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
return { session, user, isNewUser }
|
|
128
|
+
} else if (account.type === "webauthn") {
|
|
129
|
+
// Check if the account exists
|
|
130
|
+
const userByAccount = await getUserByAccount({
|
|
131
|
+
providerAccountId: account.providerAccountId,
|
|
132
|
+
provider: account.provider,
|
|
133
|
+
})
|
|
134
|
+
if (userByAccount) {
|
|
135
|
+
if (user) {
|
|
136
|
+
// If the user is already signed in with this account, we don't need to do anything
|
|
137
|
+
if (userByAccount.id === user.id) {
|
|
138
|
+
const currentAccount: AdapterAccount = { ...account, userId: user.id }
|
|
139
|
+
return { session, user, isNewUser, account: currentAccount }
|
|
140
|
+
}
|
|
141
|
+
// If the user is currently signed in, but the new account they are signing in
|
|
142
|
+
// with is already associated with another user, then we cannot link them
|
|
143
|
+
// and need to return an error.
|
|
144
|
+
throw new AccountNotLinked(
|
|
145
|
+
"The account is already associated with another user",
|
|
146
|
+
{ provider: account.provider }
|
|
147
|
+
)
|
|
148
|
+
}
|
|
149
|
+
// If there is no active session, but the account being signed in with is already
|
|
150
|
+
// associated with a valid user then create session to sign the user in.
|
|
151
|
+
session = useJwtSession
|
|
152
|
+
? {}
|
|
153
|
+
: await createSession({
|
|
154
|
+
sessionToken: generateSessionToken(),
|
|
155
|
+
userId: userByAccount.id,
|
|
156
|
+
expires: fromDate(options.session.maxAge),
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
const currentAccount: AdapterAccount = {
|
|
160
|
+
...account,
|
|
161
|
+
userId: userByAccount.id,
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
session,
|
|
165
|
+
user: userByAccount,
|
|
166
|
+
isNewUser,
|
|
167
|
+
account: currentAccount,
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// If the account doesn't exist, we'll create it
|
|
171
|
+
if (user) {
|
|
172
|
+
// If the user is already signed in and the account isn't already associated
|
|
173
|
+
// with another user account then we can go ahead and link the accounts safely.
|
|
174
|
+
await linkAccount({ ...account, userId: user.id })
|
|
175
|
+
await events.linkAccount?.({ user, account, profile })
|
|
176
|
+
|
|
177
|
+
// As they are already signed in, we don't need to do anything after linking them
|
|
178
|
+
const currentAccount: AdapterAccount = { ...account, userId: user.id }
|
|
179
|
+
return { session, user, isNewUser, account: currentAccount }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// If the user is not signed in and it looks like a new account then we
|
|
183
|
+
// check there also isn't an user account already associated with the same
|
|
184
|
+
// email address as the one in the request.
|
|
185
|
+
const userByEmail = profile.email
|
|
186
|
+
? await getUserByEmail(profile.email)
|
|
187
|
+
: null
|
|
188
|
+
if (userByEmail) {
|
|
189
|
+
// We don't trust user-provided email addresses, so we don't want to link accounts
|
|
190
|
+
// if the email address associated with the new account is already associated with
|
|
191
|
+
// an existing account.
|
|
192
|
+
throw new AccountNotLinked(
|
|
193
|
+
"Another account already exists with the same e-mail address",
|
|
194
|
+
{ provider: account.provider }
|
|
195
|
+
)
|
|
196
|
+
} else {
|
|
197
|
+
// If the current user is not logged in and the profile isn't linked to any user
|
|
198
|
+
// accounts (by email or provider account id)...
|
|
199
|
+
//
|
|
200
|
+
// If no account matching the same [provider].id or .email exists, we can
|
|
201
|
+
// create a new account for the user, link it to the OAuth account and
|
|
202
|
+
// create a new session for them so they are signed in with it.
|
|
203
|
+
user = await createUser({ ...profile })
|
|
204
|
+
}
|
|
205
|
+
await events.createUser?.({ user })
|
|
206
|
+
|
|
207
|
+
await linkAccount({ ...account, userId: user.id })
|
|
208
|
+
await events.linkAccount?.({ user, account, profile })
|
|
209
|
+
|
|
210
|
+
session = useJwtSession
|
|
211
|
+
? {}
|
|
212
|
+
: await createSession({
|
|
213
|
+
sessionToken: generateSessionToken(),
|
|
214
|
+
userId: user.id,
|
|
215
|
+
expires: fromDate(options.session.maxAge),
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
const currentAccount: AdapterAccount = { ...account, userId: user.id }
|
|
219
|
+
return { session, user, isNewUser: true, account: currentAccount }
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// If signing in with OAuth account, check to see if the account exists already
|
|
224
|
+
const userByAccount = await getUserByAccount({
|
|
225
|
+
providerAccountId: account.providerAccountId,
|
|
226
|
+
provider: account.provider,
|
|
227
|
+
})
|
|
228
|
+
if (userByAccount) {
|
|
229
|
+
if (user) {
|
|
230
|
+
// If the user is already signed in with this account, we don't need to do anything
|
|
231
|
+
if (userByAccount.id === user.id) {
|
|
232
|
+
return { session, user, isNewUser }
|
|
233
|
+
}
|
|
234
|
+
// If the user is currently signed in, but the new account they are signing in
|
|
235
|
+
// with is already associated with another user, then we cannot link them
|
|
236
|
+
// and need to return an error.
|
|
237
|
+
throw new OAuthAccountNotLinked(
|
|
238
|
+
"The account is already associated with another user",
|
|
239
|
+
{ provider: account.provider }
|
|
240
|
+
)
|
|
241
|
+
}
|
|
242
|
+
// If there is no active session, but the account being signed in with is already
|
|
243
|
+
// associated with a valid user then create session to sign the user in.
|
|
244
|
+
session = useJwtSession
|
|
245
|
+
? {}
|
|
246
|
+
: await createSession({
|
|
247
|
+
sessionToken: generateSessionToken(),
|
|
248
|
+
userId: userByAccount.id,
|
|
249
|
+
expires: fromDate(options.session.maxAge),
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return { session, user: userByAccount, isNewUser }
|
|
253
|
+
} else {
|
|
254
|
+
const { provider: p } = options as InternalOptions<"oauth" | "oidc">
|
|
255
|
+
const { type, provider, providerAccountId, userId, ...tokenSet } = account
|
|
256
|
+
const defaults = { providerAccountId, provider, type, userId }
|
|
257
|
+
account = Object.assign(p.account(tokenSet) ?? {}, defaults)
|
|
258
|
+
|
|
259
|
+
if (user) {
|
|
260
|
+
// If the user is already signed in and the OAuth account isn't already associated
|
|
261
|
+
// with another user account then we can go ahead and link the accounts safely.
|
|
262
|
+
await linkAccount({ ...account, userId: user.id })
|
|
263
|
+
await events.linkAccount?.({ user, account, profile })
|
|
264
|
+
|
|
265
|
+
// As they are already signed in, we don't need to do anything after linking them
|
|
266
|
+
return { session, user, isNewUser }
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// If the user is not signed in and it looks like a new OAuth account then we
|
|
270
|
+
// check there also isn't an user account already associated with the same
|
|
271
|
+
// email address as the one in the OAuth profile.
|
|
272
|
+
//
|
|
273
|
+
// This step is often overlooked in OAuth implementations, but covers the following cases:
|
|
274
|
+
//
|
|
275
|
+
// 1. It makes it harder for someone to accidentally create two accounts.
|
|
276
|
+
// e.g. by signin in with email, then again with an oauth account connected to the same email.
|
|
277
|
+
// 2. It makes it harder to hijack a user account using a 3rd party OAuth account.
|
|
278
|
+
// e.g. by creating an oauth account then changing the email address associated with it.
|
|
279
|
+
//
|
|
280
|
+
// It's quite common for services to automatically link accounts in this case, but it's
|
|
281
|
+
// better practice to require the user to sign in *then* link accounts to be sure
|
|
282
|
+
// someone is not exploiting a problem with a third party OAuth service.
|
|
283
|
+
//
|
|
284
|
+
// OAuth providers should require email address verification to prevent this, but in
|
|
285
|
+
// practice that is not always the case; this helps protect against that.
|
|
286
|
+
const userByEmail = profile.email
|
|
287
|
+
? await getUserByEmail(profile.email)
|
|
288
|
+
: null
|
|
289
|
+
if (userByEmail) {
|
|
290
|
+
const provider = options.provider as OAuthConfig<any>
|
|
291
|
+
if (provider?.allowDangerousEmailAccountLinking) {
|
|
292
|
+
// If you trust the oauth provider to correctly verify email addresses, you can opt-in to
|
|
293
|
+
// account linking even when the user is not signed-in.
|
|
294
|
+
user = userByEmail
|
|
295
|
+
isNewUser = false
|
|
296
|
+
} else {
|
|
297
|
+
// We end up here when we don't have an account with the same [provider].id *BUT*
|
|
298
|
+
// we do already have an account with the same email address as the one in the
|
|
299
|
+
// OAuth profile the user has just tried to sign in with.
|
|
300
|
+
//
|
|
301
|
+
// We don't want to have two accounts with the same email address, and we don't
|
|
302
|
+
// want to link them in case it's not safe to do so, so instead we prompt the user
|
|
303
|
+
// to sign in via email to verify their identity and then link the accounts.
|
|
304
|
+
throw new OAuthAccountNotLinked(
|
|
305
|
+
"Another account already exists with the same e-mail address",
|
|
306
|
+
{ provider: account.provider }
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
} else {
|
|
310
|
+
// If the current user is not logged in and the profile isn't linked to any user
|
|
311
|
+
// accounts (by email or provider account id)...
|
|
312
|
+
//
|
|
313
|
+
// If no account matching the same [provider].id or .email exists, we can
|
|
314
|
+
// create a new account for the user, link it to the OAuth account and
|
|
315
|
+
// create a new session for them so they are signed in with it.
|
|
316
|
+
user = await createUser({ ...profile, emailVerified: null })
|
|
317
|
+
isNewUser = true
|
|
318
|
+
}
|
|
319
|
+
await events.createUser?.({ user })
|
|
320
|
+
|
|
321
|
+
await linkAccount({ ...account, userId: user.id })
|
|
322
|
+
await events.linkAccount?.({ user, account, profile })
|
|
323
|
+
|
|
324
|
+
session = useJwtSession
|
|
325
|
+
? {}
|
|
326
|
+
: await createSession({
|
|
327
|
+
sessionToken: generateSessionToken(),
|
|
328
|
+
userId: user.id,
|
|
329
|
+
expires: fromDate(options.session.maxAge),
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
return { session, user, isNewUser }
|
|
333
|
+
}
|
|
334
|
+
}
|