@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
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { JWTSessionError, SessionTokenError } from "../../errors.js"
|
|
2
|
+
import { fromDate } from "../utils/date.js"
|
|
3
|
+
|
|
4
|
+
import type { Adapter } from "../../adapters.js"
|
|
5
|
+
import type { InternalOptions, ResponseInternal, Session } from "../../types.js"
|
|
6
|
+
import type { Cookie, SessionStore } from "../utils/cookie.js"
|
|
7
|
+
|
|
8
|
+
/** Return a session object filtered via `callbacks.session` */
|
|
9
|
+
export async function session(
|
|
10
|
+
options: InternalOptions,
|
|
11
|
+
sessionStore: SessionStore,
|
|
12
|
+
cookies: Cookie[],
|
|
13
|
+
isUpdate?: boolean,
|
|
14
|
+
newSession?: any
|
|
15
|
+
): Promise<ResponseInternal<Session | null>> {
|
|
16
|
+
const {
|
|
17
|
+
adapter,
|
|
18
|
+
jwt,
|
|
19
|
+
events,
|
|
20
|
+
callbacks,
|
|
21
|
+
logger,
|
|
22
|
+
session: { strategy: sessionStrategy, maxAge: sessionMaxAge },
|
|
23
|
+
} = options
|
|
24
|
+
|
|
25
|
+
const response: ResponseInternal<Session | null> = {
|
|
26
|
+
body: null,
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
...(!isUpdate && {
|
|
30
|
+
"Cache-Control": "private, no-cache, no-store",
|
|
31
|
+
Expires: "0",
|
|
32
|
+
Pragma: "no-cache",
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
cookies,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const sessionToken = sessionStore.value
|
|
39
|
+
|
|
40
|
+
if (!sessionToken) return response
|
|
41
|
+
|
|
42
|
+
if (sessionStrategy === "jwt") {
|
|
43
|
+
try {
|
|
44
|
+
const salt = options.cookies.sessionToken.name
|
|
45
|
+
const payload = await jwt.decode({ ...jwt, token: sessionToken, salt })
|
|
46
|
+
|
|
47
|
+
if (!payload) throw new Error("Invalid JWT")
|
|
48
|
+
|
|
49
|
+
// @ts-expect-error
|
|
50
|
+
const token = await callbacks.jwt({
|
|
51
|
+
token: payload,
|
|
52
|
+
...(isUpdate && { trigger: "update" }),
|
|
53
|
+
session: newSession,
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const newExpires = fromDate(sessionMaxAge)
|
|
57
|
+
|
|
58
|
+
if (token !== null) {
|
|
59
|
+
// By default, only exposes a limited subset of information to the client
|
|
60
|
+
// as needed for presentation purposes (e.g. "you are logged in as...").
|
|
61
|
+
const session = {
|
|
62
|
+
user: { name: token.name, email: token.email, image: token.picture },
|
|
63
|
+
expires: newExpires.toISOString(),
|
|
64
|
+
}
|
|
65
|
+
// @ts-expect-error
|
|
66
|
+
const newSession = await callbacks.session({ session, token })
|
|
67
|
+
|
|
68
|
+
// Return session payload as response
|
|
69
|
+
response.body = newSession
|
|
70
|
+
|
|
71
|
+
// Refresh JWT expiry by re-signing it, with an updated expiry date
|
|
72
|
+
const newToken = await jwt.encode({ ...jwt, token, salt })
|
|
73
|
+
|
|
74
|
+
// Set cookie, to also update expiry date on cookie
|
|
75
|
+
const sessionCookies = sessionStore.chunk(newToken, {
|
|
76
|
+
expires: newExpires,
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
response.cookies?.push(...sessionCookies)
|
|
80
|
+
|
|
81
|
+
await events.session?.({ session: newSession, token })
|
|
82
|
+
} else {
|
|
83
|
+
response.cookies?.push(...sessionStore.clean())
|
|
84
|
+
}
|
|
85
|
+
} catch (e) {
|
|
86
|
+
logger.error(new JWTSessionError(e as Error))
|
|
87
|
+
// If the JWT is not verifiable remove the broken session cookie(s).
|
|
88
|
+
response.cookies?.push(...sessionStore.clean())
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return response
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Retrieve session from database
|
|
95
|
+
try {
|
|
96
|
+
const { getSessionAndUser, deleteSession, updateSession } =
|
|
97
|
+
adapter as Required<Adapter>
|
|
98
|
+
let userAndSession = await getSessionAndUser(sessionToken)
|
|
99
|
+
|
|
100
|
+
// If session has expired, clean up the database
|
|
101
|
+
if (
|
|
102
|
+
userAndSession &&
|
|
103
|
+
userAndSession.session.expires.valueOf() < Date.now()
|
|
104
|
+
) {
|
|
105
|
+
await deleteSession(sessionToken)
|
|
106
|
+
userAndSession = null
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (userAndSession) {
|
|
110
|
+
const { user, session } = userAndSession
|
|
111
|
+
|
|
112
|
+
const sessionUpdateAge = options.session.updateAge
|
|
113
|
+
// Calculate last updated date to throttle write updates to database
|
|
114
|
+
// Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge
|
|
115
|
+
// e.g. ({expiry date} - 30 days) + 1 hour
|
|
116
|
+
const sessionIsDueToBeUpdatedDate =
|
|
117
|
+
session.expires.valueOf() -
|
|
118
|
+
sessionMaxAge * 1000 +
|
|
119
|
+
sessionUpdateAge * 1000
|
|
120
|
+
|
|
121
|
+
const newExpires = fromDate(sessionMaxAge)
|
|
122
|
+
// Trigger update of session expiry date and write to database, only
|
|
123
|
+
// if the session was last updated more than {sessionUpdateAge} ago
|
|
124
|
+
if (sessionIsDueToBeUpdatedDate <= Date.now()) {
|
|
125
|
+
await updateSession({
|
|
126
|
+
sessionToken: sessionToken,
|
|
127
|
+
expires: newExpires,
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Pass Session through to the session callback
|
|
132
|
+
const sessionPayload = await callbacks.session({
|
|
133
|
+
// TODO: user already passed below,
|
|
134
|
+
// remove from session object in https://github.com/nextauthjs/next-auth/pull/9702
|
|
135
|
+
// @ts-expect-error
|
|
136
|
+
session: { ...session, user },
|
|
137
|
+
user,
|
|
138
|
+
newSession,
|
|
139
|
+
...(isUpdate ? { trigger: "update" } : {}),
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// Return session payload as response
|
|
143
|
+
response.body = sessionPayload
|
|
144
|
+
|
|
145
|
+
// Set cookie again to update expiry
|
|
146
|
+
response.cookies?.push({
|
|
147
|
+
name: options.cookies.sessionToken.name,
|
|
148
|
+
value: sessionToken,
|
|
149
|
+
options: {
|
|
150
|
+
...options.cookies.sessionToken.options,
|
|
151
|
+
expires: newExpires,
|
|
152
|
+
},
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// @ts-expect-error
|
|
156
|
+
await events.session?.({ session: sessionPayload })
|
|
157
|
+
} else if (sessionToken) {
|
|
158
|
+
// If `sessionToken` was found set but it's not valid for a session then
|
|
159
|
+
// remove the sessionToken cookie from browser.
|
|
160
|
+
response.cookies?.push(...sessionStore.clean())
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
logger.error(new SessionTokenError(e as Error))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return response
|
|
167
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as checks from "../callback/oauth/checks.js"
|
|
2
|
+
import * as o from "oauth4webapi"
|
|
3
|
+
|
|
4
|
+
import type { InternalOptions, RequestInternal } from "../../../types.js"
|
|
5
|
+
import type { Cookie } from "../../utils/cookie.js"
|
|
6
|
+
import { customFetch } from "../../symbols.js"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Generates an authorization/request token URL.
|
|
10
|
+
*
|
|
11
|
+
* [OAuth 2](https://www.oauth.com/oauth2-servers/authorization/the-authorization-request/)
|
|
12
|
+
*/
|
|
13
|
+
export async function getAuthorizationUrl(
|
|
14
|
+
query: RequestInternal["query"],
|
|
15
|
+
options: InternalOptions<"oauth" | "oidc">
|
|
16
|
+
) {
|
|
17
|
+
const { logger, provider } = options
|
|
18
|
+
|
|
19
|
+
let url = provider.authorization?.url
|
|
20
|
+
let as: o.AuthorizationServer | undefined
|
|
21
|
+
|
|
22
|
+
// Falls back to authjs.dev if the user only passed params
|
|
23
|
+
if (!url || url.host === "authjs.dev") {
|
|
24
|
+
// If url is undefined, we assume that issuer is always defined
|
|
25
|
+
// We check this in assert.ts
|
|
26
|
+
|
|
27
|
+
const issuer = new URL(provider.issuer!)
|
|
28
|
+
const discoveryResponse = await o.discoveryRequest(issuer, {
|
|
29
|
+
[o.customFetch]: provider[customFetch],
|
|
30
|
+
// TODO: move away from allowing insecure HTTP requests
|
|
31
|
+
[o.allowInsecureRequests]: true,
|
|
32
|
+
})
|
|
33
|
+
const as = await o
|
|
34
|
+
.processDiscoveryResponse(issuer, discoveryResponse)
|
|
35
|
+
.catch((error) => {
|
|
36
|
+
if (!(error instanceof TypeError) || error.message !== "Invalid URL")
|
|
37
|
+
throw error
|
|
38
|
+
throw new TypeError(
|
|
39
|
+
`Discovery request responded with an invalid issuer. expected: ${issuer}`
|
|
40
|
+
)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
if (!as.authorization_endpoint) {
|
|
44
|
+
throw new TypeError(
|
|
45
|
+
"Authorization server did not provide an authorization endpoint."
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
url = new URL(as.authorization_endpoint)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const authParams = url.searchParams
|
|
53
|
+
|
|
54
|
+
let redirect_uri: string = provider.callbackUrl
|
|
55
|
+
let data: string | undefined
|
|
56
|
+
if (!options.isOnRedirectProxy && provider.redirectProxyUrl) {
|
|
57
|
+
redirect_uri = provider.redirectProxyUrl
|
|
58
|
+
data = provider.callbackUrl
|
|
59
|
+
logger.debug("using redirect proxy", { redirect_uri, data })
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const params = Object.assign(
|
|
63
|
+
{
|
|
64
|
+
response_type: "code",
|
|
65
|
+
// clientId can technically be undefined, should we check this in assert.ts or rely on the Authorization Server to do it?
|
|
66
|
+
client_id: provider.clientId,
|
|
67
|
+
redirect_uri,
|
|
68
|
+
// @ts-expect-error TODO:
|
|
69
|
+
...provider.authorization?.params,
|
|
70
|
+
},
|
|
71
|
+
Object.fromEntries(provider.authorization?.url.searchParams ?? []),
|
|
72
|
+
query
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
for (const k in params) authParams.set(k, params[k])
|
|
76
|
+
|
|
77
|
+
const cookies: Cookie[] = []
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
// Otherwise "POST /redirect_uri" wouldn't include the cookies
|
|
81
|
+
provider.authorization?.url.searchParams.get("response_mode") ===
|
|
82
|
+
"form_post"
|
|
83
|
+
) {
|
|
84
|
+
options.cookies.state.options.sameSite = "none"
|
|
85
|
+
options.cookies.state.options.secure = true
|
|
86
|
+
options.cookies.nonce.options.sameSite = "none"
|
|
87
|
+
options.cookies.nonce.options.secure = true
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const state = await checks.state.create(options, data)
|
|
91
|
+
if (state) {
|
|
92
|
+
authParams.set("state", state.value)
|
|
93
|
+
cookies.push(state.cookie)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (provider.checks?.includes("pkce")) {
|
|
97
|
+
if (as && !as.code_challenge_methods_supported?.includes("S256")) {
|
|
98
|
+
// We assume S256 PKCE support, if the server does not advertise that,
|
|
99
|
+
// a random `nonce` must be used for CSRF protection.
|
|
100
|
+
if (provider.type === "oidc") provider.checks = ["nonce"]
|
|
101
|
+
} else {
|
|
102
|
+
const { value, cookie } = await checks.pkce.create(options)
|
|
103
|
+
authParams.set("code_challenge", value)
|
|
104
|
+
authParams.set("code_challenge_method", "S256")
|
|
105
|
+
cookies.push(cookie)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const nonce = await checks.nonce.create(options)
|
|
110
|
+
if (nonce) {
|
|
111
|
+
authParams.set("nonce", nonce.value)
|
|
112
|
+
cookies.push(nonce.cookie)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// TODO: This does not work in normalizeOAuth because authorization endpoint can come from discovery
|
|
116
|
+
// Need to make normalizeOAuth async
|
|
117
|
+
if (provider.type === "oidc" && !url.searchParams.has("scope")) {
|
|
118
|
+
url.searchParams.set("scope", "openid profile email")
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
logger.debug("authorization url is ready", { url, cookies, provider })
|
|
122
|
+
return { redirect: url.toString(), cookies }
|
|
123
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getAuthorizationUrl } from "./authorization-url.js"
|
|
2
|
+
import { sendToken } from "./send-token.js"
|
|
3
|
+
|
|
4
|
+
import type { Cookie } from "../../utils/cookie.js"
|
|
5
|
+
import type {
|
|
6
|
+
InternalOptions,
|
|
7
|
+
RequestInternal,
|
|
8
|
+
ResponseInternal,
|
|
9
|
+
} from "../../../types.js"
|
|
10
|
+
|
|
11
|
+
export async function signIn(
|
|
12
|
+
request: RequestInternal,
|
|
13
|
+
cookies: Cookie[],
|
|
14
|
+
options: InternalOptions
|
|
15
|
+
): Promise<ResponseInternal> {
|
|
16
|
+
const signInUrl = `${options.url.origin}${options.basePath}/signin`
|
|
17
|
+
|
|
18
|
+
if (!options.provider) return { redirect: signInUrl, cookies }
|
|
19
|
+
|
|
20
|
+
switch (options.provider.type) {
|
|
21
|
+
case "oauth":
|
|
22
|
+
case "oidc": {
|
|
23
|
+
const { redirect, cookies: authCookies } = await getAuthorizationUrl(
|
|
24
|
+
request.query,
|
|
25
|
+
options
|
|
26
|
+
)
|
|
27
|
+
if (authCookies) cookies.push(...authCookies)
|
|
28
|
+
return { redirect, cookies }
|
|
29
|
+
}
|
|
30
|
+
case "email": {
|
|
31
|
+
const response = await sendToken(request, options)
|
|
32
|
+
return { ...response, cookies }
|
|
33
|
+
}
|
|
34
|
+
default:
|
|
35
|
+
return { redirect: signInUrl, cookies }
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { createHash, randomString, toRequest } from "../../utils/web.js"
|
|
2
|
+
import { AccessDenied } from "../../../errors.js"
|
|
3
|
+
|
|
4
|
+
import type { InternalOptions, RequestInternal } from "../../../types.js"
|
|
5
|
+
import type { Account } from "../../../types.js"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Starts an e-mail login flow, by generating a token,
|
|
9
|
+
* and sending it to the user's e-mail (with the help of a DB adapter).
|
|
10
|
+
* At the end, it returns a redirect to the `verify-request` page.
|
|
11
|
+
*/
|
|
12
|
+
export async function sendToken(
|
|
13
|
+
request: RequestInternal,
|
|
14
|
+
options: InternalOptions<"email">
|
|
15
|
+
) {
|
|
16
|
+
const { body } = request
|
|
17
|
+
const { provider, callbacks, adapter } = options
|
|
18
|
+
const normalizer = provider.normalizeIdentifier ?? defaultNormalizer
|
|
19
|
+
const email = normalizer(body?.email)
|
|
20
|
+
|
|
21
|
+
const defaultUser = { id: crypto.randomUUID(), email, emailVerified: null }
|
|
22
|
+
const user = (await adapter!.getUserByEmail(email)) ?? defaultUser
|
|
23
|
+
|
|
24
|
+
const account = {
|
|
25
|
+
providerAccountId: email,
|
|
26
|
+
userId: user.id,
|
|
27
|
+
type: "email",
|
|
28
|
+
provider: provider.id,
|
|
29
|
+
} satisfies Account
|
|
30
|
+
|
|
31
|
+
let authorized
|
|
32
|
+
try {
|
|
33
|
+
authorized = await callbacks.signIn({
|
|
34
|
+
user,
|
|
35
|
+
account,
|
|
36
|
+
email: { verificationRequest: true },
|
|
37
|
+
})
|
|
38
|
+
} catch (e) {
|
|
39
|
+
throw new AccessDenied(e as Error)
|
|
40
|
+
}
|
|
41
|
+
if (!authorized) throw new AccessDenied("AccessDenied")
|
|
42
|
+
if (typeof authorized === "string") {
|
|
43
|
+
return {
|
|
44
|
+
redirect: await callbacks.redirect({
|
|
45
|
+
url: authorized,
|
|
46
|
+
baseUrl: options.url.origin,
|
|
47
|
+
}),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const { callbackUrl, theme } = options
|
|
52
|
+
const token =
|
|
53
|
+
(await provider.generateVerificationToken?.()) ?? randomString(32)
|
|
54
|
+
|
|
55
|
+
const ONE_DAY_IN_SECONDS = 86400
|
|
56
|
+
const expires = new Date(
|
|
57
|
+
Date.now() + (provider.maxAge ?? ONE_DAY_IN_SECONDS) * 1000
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const secret = provider.secret ?? options.secret
|
|
61
|
+
|
|
62
|
+
const baseUrl = new URL(options.basePath, options.url.origin)
|
|
63
|
+
|
|
64
|
+
const sendRequest = provider.sendVerificationRequest({
|
|
65
|
+
identifier: email,
|
|
66
|
+
token,
|
|
67
|
+
expires,
|
|
68
|
+
url: `${baseUrl}/callback/${provider.id}?${new URLSearchParams({
|
|
69
|
+
callbackUrl,
|
|
70
|
+
token,
|
|
71
|
+
email,
|
|
72
|
+
})}`,
|
|
73
|
+
provider,
|
|
74
|
+
theme,
|
|
75
|
+
request: toRequest(request),
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const createToken = adapter!.createVerificationToken?.({
|
|
79
|
+
identifier: email,
|
|
80
|
+
token: await createHash(`${token}${secret}`),
|
|
81
|
+
expires,
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
await Promise.all([sendRequest, createToken])
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
redirect: `${baseUrl}/verify-request?${new URLSearchParams({
|
|
88
|
+
provider: provider.id,
|
|
89
|
+
type: provider.type,
|
|
90
|
+
})}`,
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function defaultNormalizer(email?: string) {
|
|
95
|
+
if (!email) throw new Error("Missing email from request body.")
|
|
96
|
+
|
|
97
|
+
const trimmedEmail = email.toLowerCase().trim()
|
|
98
|
+
|
|
99
|
+
// Reject email addresses with quotes to prevent address parser confusion
|
|
100
|
+
// This prevents attacks like "attacker@evil.com"@victim.com
|
|
101
|
+
if (trimmedEmail.includes('"')) {
|
|
102
|
+
throw new Error("Invalid email address format.")
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Get the first two elements only,
|
|
106
|
+
// separated by `@` from user input.
|
|
107
|
+
let [local, domain] = trimmedEmail.split("@")
|
|
108
|
+
|
|
109
|
+
// Validate that we have exactly 2 parts (local and domain)
|
|
110
|
+
if (!local || !domain || trimmedEmail.split("@").length !== 2) {
|
|
111
|
+
throw new Error("Invalid email address format.")
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// The part before "@" can contain a ","
|
|
115
|
+
// but we remove it on the domain part
|
|
116
|
+
domain = domain.split(",")[0]
|
|
117
|
+
|
|
118
|
+
// Additional validation: domain should not be empty after comma split
|
|
119
|
+
if (!domain) {
|
|
120
|
+
throw new Error("Invalid email address format.")
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return `${local}@${domain}`
|
|
124
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SignOutError } from "../../errors.js"
|
|
2
|
+
|
|
3
|
+
import type { InternalOptions, ResponseInternal } from "../../types.js"
|
|
4
|
+
import type { Cookie, SessionStore } from "../utils/cookie.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Destroys the session.
|
|
8
|
+
* If the session strategy is database,
|
|
9
|
+
* The session is also deleted from the database.
|
|
10
|
+
* In any case, the session cookie is cleared and
|
|
11
|
+
* {@link AuthConfig["events"].signOut} is emitted.
|
|
12
|
+
*/
|
|
13
|
+
export async function signOut(
|
|
14
|
+
cookies: Cookie[],
|
|
15
|
+
sessionStore: SessionStore,
|
|
16
|
+
options: InternalOptions
|
|
17
|
+
): Promise<ResponseInternal> {
|
|
18
|
+
const { jwt, events, callbackUrl: redirect, logger, session } = options
|
|
19
|
+
const sessionToken = sessionStore.value
|
|
20
|
+
if (!sessionToken) return { redirect, cookies }
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
if (session.strategy === "jwt") {
|
|
24
|
+
const salt = options.cookies.sessionToken.name
|
|
25
|
+
const token = await jwt.decode({ ...jwt, token: sessionToken, salt })
|
|
26
|
+
await events.signOut?.({ token })
|
|
27
|
+
} else {
|
|
28
|
+
const session = await options.adapter?.deleteSession(sessionToken)
|
|
29
|
+
await events.signOut?.({ session })
|
|
30
|
+
}
|
|
31
|
+
} catch (e) {
|
|
32
|
+
logger.error(new SignOutError(e as Error))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
cookies.push(...sessionStore.clean())
|
|
36
|
+
|
|
37
|
+
return { redirect, cookies }
|
|
38
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
InternalOptions,
|
|
3
|
+
RequestInternal,
|
|
4
|
+
ResponseInternal,
|
|
5
|
+
User,
|
|
6
|
+
} from "../../types.js"
|
|
7
|
+
import type { Cookie, SessionStore } from "../utils/cookie.js"
|
|
8
|
+
import { getLoggedInUser } from "../utils/session.js"
|
|
9
|
+
import {
|
|
10
|
+
assertInternalOptionsWebAuthn,
|
|
11
|
+
inferWebAuthnOptions,
|
|
12
|
+
getAuthenticationResponse,
|
|
13
|
+
getRegistrationResponse,
|
|
14
|
+
} from "../utils/webauthn-utils.js"
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Returns authentication or registration options for a WebAuthn flow
|
|
18
|
+
* depending on the parameters provided.
|
|
19
|
+
*/
|
|
20
|
+
export async function webAuthnOptions(
|
|
21
|
+
request: RequestInternal,
|
|
22
|
+
options: InternalOptions,
|
|
23
|
+
sessionStore: SessionStore,
|
|
24
|
+
cookies: Cookie[]
|
|
25
|
+
// @ts-expect-error issue with returning from a switch case
|
|
26
|
+
): Promise<ResponseInternal> {
|
|
27
|
+
// Return an error if the adapter is missing or if the provider
|
|
28
|
+
// is not a webauthn provider.
|
|
29
|
+
const narrowOptions = assertInternalOptionsWebAuthn(options)
|
|
30
|
+
const { provider } = narrowOptions
|
|
31
|
+
|
|
32
|
+
// Extract the action from the query parameters
|
|
33
|
+
const { action } = (request.query ?? {}) as Record<string, unknown>
|
|
34
|
+
|
|
35
|
+
// Action must be either "register", "authenticate", or undefined
|
|
36
|
+
if (
|
|
37
|
+
action !== "register" &&
|
|
38
|
+
action !== "authenticate" &&
|
|
39
|
+
typeof action !== "undefined"
|
|
40
|
+
) {
|
|
41
|
+
return {
|
|
42
|
+
status: 400,
|
|
43
|
+
body: { error: "Invalid action" },
|
|
44
|
+
cookies,
|
|
45
|
+
headers: {
|
|
46
|
+
"Content-Type": "application/json",
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Get the user info from the session
|
|
52
|
+
const sessionUser = await getLoggedInUser(options, sessionStore)
|
|
53
|
+
|
|
54
|
+
// Extract user info from request
|
|
55
|
+
// If session user exists, we don't need to call getUserInfo
|
|
56
|
+
const getUserInfoResponse = sessionUser
|
|
57
|
+
? {
|
|
58
|
+
user: sessionUser,
|
|
59
|
+
exists: true,
|
|
60
|
+
}
|
|
61
|
+
: await provider.getUserInfo(options, request)
|
|
62
|
+
|
|
63
|
+
const userInfo = getUserInfoResponse?.user
|
|
64
|
+
|
|
65
|
+
// Make a decision on what kind of webauthn options to return
|
|
66
|
+
const decision = inferWebAuthnOptions(
|
|
67
|
+
action,
|
|
68
|
+
!!sessionUser,
|
|
69
|
+
getUserInfoResponse
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
switch (decision) {
|
|
73
|
+
case "authenticate":
|
|
74
|
+
return getAuthenticationResponse(
|
|
75
|
+
narrowOptions,
|
|
76
|
+
request,
|
|
77
|
+
userInfo,
|
|
78
|
+
cookies
|
|
79
|
+
)
|
|
80
|
+
case "register":
|
|
81
|
+
if (typeof userInfo?.email === "string") {
|
|
82
|
+
return getRegistrationResponse(
|
|
83
|
+
narrowOptions,
|
|
84
|
+
request,
|
|
85
|
+
userInfo as User & { email: string },
|
|
86
|
+
cookies
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
break
|
|
90
|
+
default:
|
|
91
|
+
return {
|
|
92
|
+
status: 400,
|
|
93
|
+
body: { error: "Invalid request" },
|
|
94
|
+
cookies,
|
|
95
|
+
headers: {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { UnknownAction } from "../errors.js"
|
|
2
|
+
import { SessionStore } from "./utils/cookie.js"
|
|
3
|
+
import { init } from "./init.js"
|
|
4
|
+
import renderPage from "./pages/index.js"
|
|
5
|
+
import * as actions from "./actions/index.js"
|
|
6
|
+
import { validateCSRF } from "./actions/callback/oauth/csrf-token.js"
|
|
7
|
+
|
|
8
|
+
import type { RequestInternal, ResponseInternal } from "../types.js"
|
|
9
|
+
import type { AuthConfig } from "../index.js"
|
|
10
|
+
import { skipCSRFCheck } from "./symbols.js"
|
|
11
|
+
|
|
12
|
+
export { customFetch, raw, skipCSRFCheck } from "./symbols.js"
|
|
13
|
+
|
|
14
|
+
/** @internal */
|
|
15
|
+
export async function AuthInternal(
|
|
16
|
+
request: RequestInternal,
|
|
17
|
+
authOptions: AuthConfig
|
|
18
|
+
): Promise<ResponseInternal> {
|
|
19
|
+
const { action, providerId, error, method } = request
|
|
20
|
+
|
|
21
|
+
const csrfDisabled = authOptions.skipCSRFCheck === skipCSRFCheck
|
|
22
|
+
|
|
23
|
+
const { options, cookies } = await init({
|
|
24
|
+
authOptions,
|
|
25
|
+
action,
|
|
26
|
+
providerId,
|
|
27
|
+
url: request.url,
|
|
28
|
+
callbackUrl: request.body?.callbackUrl ?? request.query?.callbackUrl,
|
|
29
|
+
csrfToken: request.body?.csrfToken,
|
|
30
|
+
cookies: request.cookies,
|
|
31
|
+
isPost: method === "POST",
|
|
32
|
+
csrfDisabled,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const sessionStore = new SessionStore(
|
|
36
|
+
options.cookies.sessionToken,
|
|
37
|
+
request.cookies,
|
|
38
|
+
options.logger
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if (method === "GET") {
|
|
42
|
+
const render = renderPage({ ...options, query: request.query, cookies })
|
|
43
|
+
switch (action) {
|
|
44
|
+
case "callback":
|
|
45
|
+
return await actions.callback(request, options, sessionStore, cookies)
|
|
46
|
+
case "csrf":
|
|
47
|
+
return render.csrf(csrfDisabled, options, cookies)
|
|
48
|
+
case "error":
|
|
49
|
+
return render.error(error)
|
|
50
|
+
case "providers":
|
|
51
|
+
return render.providers(options.providers)
|
|
52
|
+
case "session":
|
|
53
|
+
return await actions.session(options, sessionStore, cookies)
|
|
54
|
+
case "signin":
|
|
55
|
+
return render.signin(providerId, error)
|
|
56
|
+
case "signout":
|
|
57
|
+
return render.signout()
|
|
58
|
+
case "verify-request":
|
|
59
|
+
return render.verifyRequest()
|
|
60
|
+
case "webauthn-options":
|
|
61
|
+
return await actions.webAuthnOptions(
|
|
62
|
+
request,
|
|
63
|
+
options,
|
|
64
|
+
sessionStore,
|
|
65
|
+
cookies
|
|
66
|
+
)
|
|
67
|
+
default:
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
const { csrfTokenVerified } = options
|
|
71
|
+
switch (action) {
|
|
72
|
+
case "callback":
|
|
73
|
+
if (options.provider.type === "credentials")
|
|
74
|
+
// Verified CSRF Token required for credentials providers only
|
|
75
|
+
validateCSRF(action, csrfTokenVerified)
|
|
76
|
+
return await actions.callback(request, options, sessionStore, cookies)
|
|
77
|
+
case "session":
|
|
78
|
+
validateCSRF(action, csrfTokenVerified)
|
|
79
|
+
return await actions.session(
|
|
80
|
+
options,
|
|
81
|
+
sessionStore,
|
|
82
|
+
cookies,
|
|
83
|
+
true,
|
|
84
|
+
request.body?.data
|
|
85
|
+
)
|
|
86
|
+
case "signin":
|
|
87
|
+
validateCSRF(action, csrfTokenVerified)
|
|
88
|
+
return await actions.signIn(request, cookies, options)
|
|
89
|
+
|
|
90
|
+
case "signout":
|
|
91
|
+
validateCSRF(action, csrfTokenVerified)
|
|
92
|
+
return await actions.signOut(cookies, sessionStore, options)
|
|
93
|
+
default:
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
throw new UnknownAction(`Cannot handle action: ${action}`)
|
|
97
|
+
}
|