mulguard 1.1.6 → 1.1.8
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 +21 -1078
- package/adapters.d.ts +2 -0
- package/adapters.d.ts.map +1 -0
- package/adapters.js +1 -0
- package/index.d.ts +329 -0
- package/index.d.ts.map +1 -0
- package/index.js +145 -0
- package/jwt.d.ts +9 -0
- package/jwt.d.ts.map +1 -0
- package/jwt.js +8 -0
- package/lib/actions.d.ts +13 -0
- package/lib/actions.d.ts.map +1 -0
- package/lib/actions.js +86 -0
- package/lib/client.d.ts +104 -0
- package/lib/client.d.ts.map +1 -0
- package/lib/client.js +95 -0
- package/lib/env.d.ts +12 -0
- package/lib/env.d.ts.map +1 -0
- package/lib/env.js +38 -0
- package/lib/index.d.ts +56 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +187 -0
- package/lib/types.d.ts +24 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +1 -0
- package/middleware.d.ts +9 -0
- package/middleware.d.ts.map +1 -0
- package/middleware.js +12 -0
- package/next.d.ts +9 -0
- package/next.d.ts.map +1 -0
- package/next.js +12 -0
- package/package.json +117 -73
- package/providers/42-school.d.ts +3 -0
- package/providers/42-school.d.ts.map +1 -0
- package/providers/42-school.js +2 -0
- package/providers/apple.d.ts +3 -0
- package/providers/apple.d.ts.map +1 -0
- package/providers/apple.js +2 -0
- package/providers/asgardeo.d.ts +3 -0
- package/providers/asgardeo.d.ts.map +1 -0
- package/providers/asgardeo.js +2 -0
- package/providers/atlassian.d.ts +3 -0
- package/providers/atlassian.d.ts.map +1 -0
- package/providers/atlassian.js +2 -0
- package/providers/auth0.d.ts +3 -0
- package/providers/auth0.d.ts.map +1 -0
- package/providers/auth0.js +2 -0
- package/providers/authentik.d.ts +3 -0
- package/providers/authentik.d.ts.map +1 -0
- package/providers/authentik.js +2 -0
- package/providers/azure-ad-b2c.d.ts +3 -0
- package/providers/azure-ad-b2c.d.ts.map +1 -0
- package/providers/azure-ad-b2c.js +2 -0
- package/providers/azure-ad.d.ts +3 -0
- package/providers/azure-ad.d.ts.map +1 -0
- package/providers/azure-ad.js +2 -0
- package/providers/azure-devops.d.ts +3 -0
- package/providers/azure-devops.d.ts.map +1 -0
- package/providers/azure-devops.js +2 -0
- package/providers/bankid-no.d.ts +3 -0
- package/providers/bankid-no.d.ts.map +1 -0
- package/providers/bankid-no.js +2 -0
- package/providers/battlenet.d.ts +3 -0
- package/providers/battlenet.d.ts.map +1 -0
- package/providers/battlenet.js +2 -0
- package/providers/beyondidentity.d.ts +3 -0
- package/providers/beyondidentity.d.ts.map +1 -0
- package/providers/beyondidentity.js +2 -0
- package/providers/bitbucket.d.ts +3 -0
- package/providers/bitbucket.d.ts.map +1 -0
- package/providers/bitbucket.js +2 -0
- package/providers/box.d.ts +3 -0
- package/providers/box.d.ts.map +1 -0
- package/providers/box.js +2 -0
- package/providers/boxyhq-saml.d.ts +3 -0
- package/providers/boxyhq-saml.d.ts.map +1 -0
- package/providers/boxyhq-saml.js +2 -0
- package/providers/bungie.d.ts +3 -0
- package/providers/bungie.d.ts.map +1 -0
- package/providers/bungie.js +2 -0
- package/providers/click-up.d.ts +3 -0
- package/providers/click-up.d.ts.map +1 -0
- package/providers/click-up.js +2 -0
- package/providers/cognito.d.ts +3 -0
- package/providers/cognito.d.ts.map +1 -0
- package/providers/cognito.js +2 -0
- package/providers/coinbase.d.ts +3 -0
- package/providers/coinbase.d.ts.map +1 -0
- package/providers/coinbase.js +2 -0
- package/providers/concept2.d.ts +3 -0
- package/providers/concept2.d.ts.map +1 -0
- package/providers/concept2.js +2 -0
- package/providers/credentials.d.ts +3 -0
- package/providers/credentials.d.ts.map +1 -0
- package/providers/credentials.js +2 -0
- package/providers/descope.d.ts +3 -0
- package/providers/descope.d.ts.map +1 -0
- package/providers/descope.js +2 -0
- package/providers/discord.d.ts +3 -0
- package/providers/discord.d.ts.map +1 -0
- package/providers/discord.js +2 -0
- package/providers/dribbble.d.ts +3 -0
- package/providers/dribbble.d.ts.map +1 -0
- package/providers/dribbble.js +2 -0
- package/providers/dropbox.d.ts +3 -0
- package/providers/dropbox.d.ts.map +1 -0
- package/providers/dropbox.js +2 -0
- package/providers/duende-identity-server6.d.ts +3 -0
- package/providers/duende-identity-server6.d.ts.map +1 -0
- package/providers/duende-identity-server6.js +2 -0
- package/providers/email.d.ts +3 -0
- package/providers/email.d.ts.map +1 -0
- package/providers/email.js +2 -0
- package/providers/eventbrite.d.ts +3 -0
- package/providers/eventbrite.d.ts.map +1 -0
- package/providers/eventbrite.js +2 -0
- package/providers/eveonline.d.ts +3 -0
- package/providers/eveonline.d.ts.map +1 -0
- package/providers/eveonline.js +2 -0
- package/providers/facebook.d.ts +3 -0
- package/providers/facebook.d.ts.map +1 -0
- package/providers/facebook.js +2 -0
- package/providers/faceit.d.ts +3 -0
- package/providers/faceit.d.ts.map +1 -0
- package/providers/faceit.js +2 -0
- package/providers/figma.d.ts +3 -0
- package/providers/figma.d.ts.map +1 -0
- package/providers/figma.js +2 -0
- package/providers/forwardemail.d.ts +3 -0
- package/providers/forwardemail.d.ts.map +1 -0
- package/providers/forwardemail.js +2 -0
- package/providers/foursquare.d.ts +3 -0
- package/providers/foursquare.d.ts.map +1 -0
- package/providers/foursquare.js +2 -0
- package/providers/freshbooks.d.ts +3 -0
- package/providers/freshbooks.d.ts.map +1 -0
- package/providers/freshbooks.js +2 -0
- package/providers/frontegg.d.ts +3 -0
- package/providers/frontegg.d.ts.map +1 -0
- package/providers/frontegg.js +2 -0
- package/providers/fusionauth.d.ts +3 -0
- package/providers/fusionauth.d.ts.map +1 -0
- package/providers/fusionauth.js +2 -0
- package/providers/github.d.ts +3 -0
- package/providers/github.d.ts.map +1 -0
- package/providers/github.js +2 -0
- package/providers/gitlab.d.ts +3 -0
- package/providers/gitlab.d.ts.map +1 -0
- package/providers/gitlab.js +2 -0
- package/providers/google.d.ts +3 -0
- package/providers/google.d.ts.map +1 -0
- package/providers/google.js +2 -0
- package/providers/hubspot.d.ts +3 -0
- package/providers/hubspot.d.ts.map +1 -0
- package/providers/hubspot.js +2 -0
- package/providers/huggingface.d.ts +3 -0
- package/providers/huggingface.d.ts.map +1 -0
- package/providers/huggingface.js +2 -0
- package/providers/identity-server4.d.ts +3 -0
- package/providers/identity-server4.d.ts.map +1 -0
- package/providers/identity-server4.js +2 -0
- package/providers/index.d.ts +2 -0
- package/providers/index.d.ts.map +1 -0
- package/providers/index.js +1 -0
- package/providers/instagram.d.ts +3 -0
- package/providers/instagram.d.ts.map +1 -0
- package/providers/instagram.js +2 -0
- package/providers/kakao.d.ts +3 -0
- package/providers/kakao.d.ts.map +1 -0
- package/providers/kakao.js +2 -0
- package/providers/keycloak.d.ts +3 -0
- package/providers/keycloak.d.ts.map +1 -0
- package/providers/keycloak.js +2 -0
- package/providers/kinde.d.ts +3 -0
- package/providers/kinde.d.ts.map +1 -0
- package/providers/kinde.js +2 -0
- package/providers/line.d.ts +3 -0
- package/providers/line.d.ts.map +1 -0
- package/providers/line.js +2 -0
- package/providers/linkedin.d.ts +3 -0
- package/providers/linkedin.d.ts.map +1 -0
- package/providers/linkedin.js +2 -0
- package/providers/logto.d.ts +3 -0
- package/providers/logto.d.ts.map +1 -0
- package/providers/logto.js +2 -0
- package/providers/loops.d.ts +3 -0
- package/providers/loops.d.ts.map +1 -0
- package/providers/loops.js +2 -0
- package/providers/mailchimp.d.ts +3 -0
- package/providers/mailchimp.d.ts.map +1 -0
- package/providers/mailchimp.js +2 -0
- package/providers/mailgun.d.ts +3 -0
- package/providers/mailgun.d.ts.map +1 -0
- package/providers/mailgun.js +2 -0
- package/providers/mailru.d.ts +3 -0
- package/providers/mailru.d.ts.map +1 -0
- package/providers/mailru.js +2 -0
- package/providers/mastodon.d.ts +3 -0
- package/providers/mastodon.d.ts.map +1 -0
- package/providers/mastodon.js +2 -0
- package/providers/mattermost.d.ts +3 -0
- package/providers/mattermost.d.ts.map +1 -0
- package/providers/mattermost.js +2 -0
- package/providers/medium.d.ts +3 -0
- package/providers/medium.d.ts.map +1 -0
- package/providers/medium.js +2 -0
- package/providers/microsoft-entra-id.d.ts +3 -0
- package/providers/microsoft-entra-id.d.ts.map +1 -0
- package/providers/microsoft-entra-id.js +2 -0
- package/providers/naver.d.ts +3 -0
- package/providers/naver.d.ts.map +1 -0
- package/providers/naver.js +2 -0
- package/providers/netlify.d.ts +3 -0
- package/providers/netlify.d.ts.map +1 -0
- package/providers/netlify.js +2 -0
- package/providers/netsuite.d.ts +3 -0
- package/providers/netsuite.d.ts.map +1 -0
- package/providers/netsuite.js +2 -0
- package/providers/nextcloud.d.ts +3 -0
- package/providers/nextcloud.d.ts.map +1 -0
- package/providers/nextcloud.js +2 -0
- package/providers/nodemailer.d.ts +3 -0
- package/providers/nodemailer.d.ts.map +1 -0
- package/providers/nodemailer.js +2 -0
- package/providers/notion.d.ts +3 -0
- package/providers/notion.d.ts.map +1 -0
- package/providers/notion.js +2 -0
- package/providers/okta.d.ts +3 -0
- package/providers/okta.d.ts.map +1 -0
- package/providers/okta.js +2 -0
- package/providers/onelogin.d.ts +3 -0
- package/providers/onelogin.d.ts.map +1 -0
- package/providers/onelogin.js +2 -0
- package/providers/ory-hydra.d.ts +3 -0
- package/providers/ory-hydra.d.ts.map +1 -0
- package/providers/ory-hydra.js +2 -0
- package/providers/osso.d.ts +3 -0
- package/providers/osso.d.ts.map +1 -0
- package/providers/osso.js +2 -0
- package/providers/osu.d.ts +3 -0
- package/providers/osu.d.ts.map +1 -0
- package/providers/osu.js +2 -0
- package/providers/passage.d.ts +3 -0
- package/providers/passage.d.ts.map +1 -0
- package/providers/passage.js +2 -0
- package/providers/passkey.d.ts +3 -0
- package/providers/passkey.d.ts.map +1 -0
- package/providers/passkey.js +2 -0
- package/providers/patreon.d.ts +3 -0
- package/providers/patreon.d.ts.map +1 -0
- package/providers/patreon.js +2 -0
- package/providers/ping-id.d.ts +3 -0
- package/providers/ping-id.d.ts.map +1 -0
- package/providers/ping-id.js +2 -0
- package/providers/pinterest.d.ts +3 -0
- package/providers/pinterest.d.ts.map +1 -0
- package/providers/pinterest.js +2 -0
- package/providers/pipedrive.d.ts +3 -0
- package/providers/pipedrive.d.ts.map +1 -0
- package/providers/pipedrive.js +2 -0
- package/providers/postmark.d.ts +3 -0
- package/providers/postmark.d.ts.map +1 -0
- package/providers/postmark.js +2 -0
- package/providers/reddit.d.ts +3 -0
- package/providers/reddit.d.ts.map +1 -0
- package/providers/reddit.js +2 -0
- package/providers/resend.d.ts +3 -0
- package/providers/resend.d.ts.map +1 -0
- package/providers/resend.js +2 -0
- package/providers/roblox.d.ts +3 -0
- package/providers/roblox.d.ts.map +1 -0
- package/providers/roblox.js +2 -0
- package/providers/salesforce.d.ts +3 -0
- package/providers/salesforce.d.ts.map +1 -0
- package/providers/salesforce.js +2 -0
- package/providers/sendgrid.d.ts +3 -0
- package/providers/sendgrid.d.ts.map +1 -0
- package/providers/sendgrid.js +2 -0
- package/providers/simplelogin.d.ts +3 -0
- package/providers/simplelogin.d.ts.map +1 -0
- package/providers/simplelogin.js +2 -0
- package/providers/slack.d.ts +3 -0
- package/providers/slack.d.ts.map +1 -0
- package/providers/slack.js +2 -0
- package/providers/spotify.d.ts +3 -0
- package/providers/spotify.d.ts.map +1 -0
- package/providers/spotify.js +2 -0
- package/providers/strava.d.ts +3 -0
- package/providers/strava.d.ts.map +1 -0
- package/providers/strava.js +2 -0
- package/providers/threads.d.ts +3 -0
- package/providers/threads.d.ts.map +1 -0
- package/providers/threads.js +2 -0
- package/providers/tiktok.d.ts +3 -0
- package/providers/tiktok.d.ts.map +1 -0
- package/providers/tiktok.js +2 -0
- package/providers/todoist.d.ts +3 -0
- package/providers/todoist.d.ts.map +1 -0
- package/providers/todoist.js +2 -0
- package/providers/trakt.d.ts +3 -0
- package/providers/trakt.d.ts.map +1 -0
- package/providers/trakt.js +2 -0
- package/providers/twitch.d.ts +3 -0
- package/providers/twitch.d.ts.map +1 -0
- package/providers/twitch.js +2 -0
- package/providers/twitter.d.ts +3 -0
- package/providers/twitter.d.ts.map +1 -0
- package/providers/twitter.js +2 -0
- package/providers/united-effects.d.ts +3 -0
- package/providers/united-effects.d.ts.map +1 -0
- package/providers/united-effects.js +2 -0
- package/providers/vipps.d.ts +3 -0
- package/providers/vipps.d.ts.map +1 -0
- package/providers/vipps.js +2 -0
- package/providers/vk.d.ts +3 -0
- package/providers/vk.d.ts.map +1 -0
- package/providers/vk.js +2 -0
- package/providers/webauthn.d.ts +3 -0
- package/providers/webauthn.d.ts.map +1 -0
- package/providers/webauthn.js +2 -0
- package/providers/webex.d.ts +3 -0
- package/providers/webex.d.ts.map +1 -0
- package/providers/webex.js +2 -0
- package/providers/wechat.d.ts +3 -0
- package/providers/wechat.d.ts.map +1 -0
- package/providers/wechat.js +2 -0
- package/providers/wikimedia.d.ts +3 -0
- package/providers/wikimedia.d.ts.map +1 -0
- package/providers/wikimedia.js +2 -0
- package/providers/wordpress.d.ts +3 -0
- package/providers/wordpress.d.ts.map +1 -0
- package/providers/wordpress.js +2 -0
- package/providers/workos.d.ts +3 -0
- package/providers/workos.d.ts.map +1 -0
- package/providers/workos.js +2 -0
- package/providers/yandex.d.ts +3 -0
- package/providers/yandex.d.ts.map +1 -0
- package/providers/yandex.js +2 -0
- package/providers/zitadel.d.ts +3 -0
- package/providers/zitadel.d.ts.map +1 -0
- package/providers/zitadel.js +2 -0
- package/providers/zoho.d.ts +3 -0
- package/providers/zoho.d.ts.map +1 -0
- package/providers/zoho.js +2 -0
- package/providers/zoom.d.ts +3 -0
- package/providers/zoom.d.ts.map +1 -0
- package/providers/zoom.js +2 -0
- package/react.d.ts +102 -0
- package/react.d.ts.map +1 -0
- package/react.js +361 -0
- package/src/adapters.ts +1 -0
- package/src/index.ts +430 -0
- package/src/jwt.ts +9 -0
- package/src/lib/actions.ts +144 -0
- package/src/lib/client.ts +245 -0
- package/src/lib/env.ts +36 -0
- package/src/lib/index.ts +313 -0
- package/src/lib/types.ts +30 -0
- package/src/middleware.ts +16 -0
- package/src/next.ts +16 -0
- package/src/providers/42-school.ts +2 -0
- package/src/providers/apple.ts +2 -0
- package/src/providers/asgardeo.ts +2 -0
- package/src/providers/atlassian.ts +2 -0
- package/src/providers/auth0.ts +2 -0
- package/src/providers/authentik.ts +2 -0
- package/src/providers/azure-ad-b2c.ts +2 -0
- package/src/providers/azure-ad.ts +2 -0
- package/src/providers/azure-devops.ts +2 -0
- package/src/providers/bankid-no.ts +2 -0
- package/src/providers/battlenet.ts +2 -0
- package/src/providers/beyondidentity.ts +2 -0
- package/src/providers/bitbucket.ts +2 -0
- package/src/providers/box.ts +2 -0
- package/src/providers/boxyhq-saml.ts +2 -0
- package/src/providers/bungie.ts +2 -0
- package/src/providers/click-up.ts +2 -0
- package/src/providers/cognito.ts +2 -0
- package/src/providers/coinbase.ts +2 -0
- package/src/providers/concept2.ts +2 -0
- package/src/providers/credentials.ts +2 -0
- package/src/providers/descope.ts +2 -0
- package/src/providers/discord.ts +2 -0
- package/src/providers/dribbble.ts +2 -0
- package/src/providers/dropbox.ts +2 -0
- package/src/providers/duende-identity-server6.ts +2 -0
- package/src/providers/email.ts +2 -0
- package/src/providers/eventbrite.ts +2 -0
- package/src/providers/eveonline.ts +2 -0
- package/src/providers/facebook.ts +2 -0
- package/src/providers/faceit.ts +2 -0
- package/src/providers/figma.ts +2 -0
- package/src/providers/forwardemail.ts +2 -0
- package/src/providers/foursquare.ts +2 -0
- package/src/providers/freshbooks.ts +2 -0
- package/src/providers/frontegg.ts +2 -0
- package/src/providers/fusionauth.ts +2 -0
- package/src/providers/github.ts +2 -0
- package/src/providers/gitlab.ts +2 -0
- package/src/providers/google.ts +2 -0
- package/src/providers/hubspot.ts +2 -0
- package/src/providers/huggingface.ts +2 -0
- package/src/providers/identity-server4.ts +2 -0
- package/src/providers/index.ts +1 -0
- package/src/providers/instagram.ts +2 -0
- package/src/providers/kakao.ts +2 -0
- package/src/providers/keycloak.ts +2 -0
- package/src/providers/kinde.ts +2 -0
- package/src/providers/line.ts +2 -0
- package/src/providers/linkedin.ts +2 -0
- package/src/providers/logto.ts +2 -0
- package/src/providers/loops.ts +2 -0
- package/src/providers/mailchimp.ts +2 -0
- package/src/providers/mailgun.ts +2 -0
- package/src/providers/mailru.ts +2 -0
- package/src/providers/mastodon.ts +2 -0
- package/src/providers/mattermost.ts +2 -0
- package/src/providers/medium.ts +2 -0
- package/src/providers/microsoft-entra-id.ts +2 -0
- package/src/providers/naver.ts +2 -0
- package/src/providers/netlify.ts +2 -0
- package/src/providers/netsuite.ts +2 -0
- package/src/providers/nextcloud.ts +2 -0
- package/src/providers/nodemailer.ts +2 -0
- package/src/providers/notion.ts +2 -0
- package/src/providers/okta.ts +2 -0
- package/src/providers/onelogin.ts +2 -0
- package/src/providers/ory-hydra.ts +2 -0
- package/src/providers/osso.ts +2 -0
- package/src/providers/osu.ts +2 -0
- package/src/providers/passage.ts +2 -0
- package/src/providers/passkey.ts +2 -0
- package/src/providers/patreon.ts +2 -0
- package/src/providers/ping-id.ts +2 -0
- package/src/providers/pinterest.ts +2 -0
- package/src/providers/pipedrive.ts +2 -0
- package/src/providers/postmark.ts +2 -0
- package/src/providers/reddit.ts +2 -0
- package/src/providers/resend.ts +2 -0
- package/src/providers/roblox.ts +2 -0
- package/src/providers/salesforce.ts +2 -0
- package/src/providers/sendgrid.ts +2 -0
- package/src/providers/simplelogin.ts +2 -0
- package/src/providers/slack.ts +2 -0
- package/src/providers/spotify.ts +2 -0
- package/src/providers/strava.ts +2 -0
- package/src/providers/threads.ts +2 -0
- package/src/providers/tiktok.ts +2 -0
- package/src/providers/todoist.ts +2 -0
- package/src/providers/trakt.ts +2 -0
- package/src/providers/twitch.ts +2 -0
- package/src/providers/twitter.ts +2 -0
- package/src/providers/united-effects.ts +2 -0
- package/src/providers/vipps.ts +2 -0
- package/src/providers/vk.ts +2 -0
- package/src/providers/webauthn.ts +2 -0
- package/src/providers/webex.ts +2 -0
- package/src/providers/wechat.ts +2 -0
- package/src/providers/wikimedia.ts +2 -0
- package/src/providers/wordpress.ts +2 -0
- package/src/providers/workos.ts +2 -0
- package/src/providers/yandex.ts +2 -0
- package/src/providers/zitadel.ts +2 -0
- package/src/providers/zoho.ts +2 -0
- package/src/providers/zoom.ts +2 -0
- package/src/react.tsx +546 -0
- package/src/webauthn.ts +152 -0
- package/webauthn.d.ts +9 -0
- package/webauthn.d.ts.map +1 -0
- package/webauthn.js +92 -0
- package/LICENSE +0 -70
- package/dist/actions-CExpv_dD.js +0 -1
- package/dist/actions-DeCfLtHA.mjs +0 -184
- package/dist/client/hooks.d.ts +0 -122
- package/dist/client/index.d.ts +0 -5
- package/dist/client/index.js +0 -1
- package/dist/client/index.mjs +0 -478
- package/dist/client/provider.d.ts +0 -69
- package/dist/client/server-actions-helper.d.ts +0 -22
- package/dist/components/AccountPicker.d.ts +0 -11
- package/dist/components/OAuthButton.d.ts +0 -11
- package/dist/components/PassKeyButton.d.ts +0 -11
- package/dist/components/PassKeyRegister.d.ts +0 -10
- package/dist/components/TwoFactorSetup.d.ts +0 -8
- package/dist/components/TwoFactorVerify.d.ts +0 -9
- package/dist/core/account-picker/encryption.d.ts +0 -22
- package/dist/core/account-picker/index.d.ts +0 -22
- package/dist/core/auth/index.d.ts +0 -40
- package/dist/core/auth/oauth-providers.d.ts +0 -197
- package/dist/core/auth/oauth-state-store-cookie.d.ts +0 -83
- package/dist/core/auth/oauth-state-store-redis.d.ts +0 -25
- package/dist/core/auth/oauth-state-store.d.ts +0 -45
- package/dist/core/auth/oauth.d.ts +0 -20
- package/dist/core/auth/passkey.d.ts +0 -35
- package/dist/core/auth/password.d.ts +0 -22
- package/dist/core/auth/signin-unified.d.ts +0 -33
- package/dist/core/auth/two-factor.d.ts +0 -28
- package/dist/core/client/index.d.ts +0 -132
- package/dist/core/client/token-refresh-manager.d.ts +0 -48
- package/dist/core/index.d.ts +0 -11
- package/dist/core/mulguard/auth-handlers.d.ts +0 -100
- package/dist/core/mulguard/defaults.d.ts +0 -58
- package/dist/core/mulguard/index.d.ts +0 -9
- package/dist/core/mulguard/oauth-handler.d.ts +0 -93
- package/dist/core/mulguard/session-manager.d.ts +0 -94
- package/dist/core/security/csrf.d.ts +0 -46
- package/dist/core/security/headers.d.ts +0 -24
- package/dist/core/security/index.d.ts +0 -132
- package/dist/core/security/rate-limit.d.ts +0 -39
- package/dist/core/security/validation.d.ts +0 -251
- package/dist/core/security/xss.d.ts +0 -20
- package/dist/core/session/index.d.ts +0 -35
- package/dist/core/types/auth.d.ts +0 -290
- package/dist/core/types/errors.d.ts +0 -200
- package/dist/core/types/index.d.ts +0 -462
- package/dist/core/utils/auth-helpers.d.ts +0 -136
- package/dist/core/utils/logger.d.ts +0 -121
- package/dist/handlers/api.d.ts +0 -10
- package/dist/handlers/route.d.ts +0 -76
- package/dist/index/index.js +0 -1
- package/dist/index/index.mjs +0 -2229
- package/dist/index.d.ts +0 -21
- package/dist/middleware/index.d.ts +0 -28
- package/dist/middleware/proxy.d.ts +0 -53
- package/dist/middleware/security.d.ts +0 -9
- package/dist/mulguard.d.ts +0 -373
- package/dist/oauth-state-DKle8eCr.mjs +0 -289
- package/dist/oauth-state-DlvrCV11.js +0 -1
- package/dist/server/actions.d.ts +0 -86
- package/dist/server/auth.d.ts +0 -65
- package/dist/server/cookies.d.ts +0 -42
- package/dist/server/helpers.d.ts +0 -10
- package/dist/server/index.d.ts +0 -14
- package/dist/server/index.js +0 -1
- package/dist/server/index.mjs +0 -31
- package/dist/server/middleware.d.ts +0 -39
- package/dist/server/oauth-state.d.ts +0 -30
- package/dist/server/session-helpers.d.ts +0 -26
- package/dist/server/session.d.ts +0 -28
- package/dist/server/utils.d.ts +0 -10
package/src/react.tsx
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* MulGuard is the official integration of Auth.js for Next.js applications. It supports both
|
|
4
|
+
* [Client Components](https://nextjs.org/docs/app/building-your-application/rendering/client-components) and the
|
|
5
|
+
* [Pages Router](https://nextjs.org/docs/pages). It includes methods for signing in, signing out, hooks, and a React
|
|
6
|
+
* Context provider to wrap your application and make session data available anywhere.
|
|
7
|
+
*
|
|
8
|
+
* For use in [Server Actions](https://nextjs.org/docs/app/api-reference/functions/server-actions), check out [these methods](https://authjs.dev/guides/upgrade-to-v5#methods)
|
|
9
|
+
*
|
|
10
|
+
* @module react
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
"use client"
|
|
14
|
+
|
|
15
|
+
import * as React from "react"
|
|
16
|
+
import {
|
|
17
|
+
apiBaseUrl,
|
|
18
|
+
ClientSessionError,
|
|
19
|
+
fetchData,
|
|
20
|
+
now,
|
|
21
|
+
parseUrl,
|
|
22
|
+
useOnline,
|
|
23
|
+
} from "./lib/client.js"
|
|
24
|
+
|
|
25
|
+
import type { ProviderId } from "@mulverse/mulguard-core/providers"
|
|
26
|
+
import type { LoggerInstance, Session } from "@mulverse/mulguard-core/types"
|
|
27
|
+
import type {
|
|
28
|
+
AuthClientConfig,
|
|
29
|
+
ClientSafeProvider,
|
|
30
|
+
SessionProviderProps,
|
|
31
|
+
SignInAuthorizationParams,
|
|
32
|
+
SignInOptions,
|
|
33
|
+
SignInResponse,
|
|
34
|
+
SignOutParams,
|
|
35
|
+
SignOutResponse,
|
|
36
|
+
UseSessionOptions,
|
|
37
|
+
} from "./lib/client.js"
|
|
38
|
+
|
|
39
|
+
// TODO: Remove/move to core?
|
|
40
|
+
export type {
|
|
41
|
+
SignInOptions,
|
|
42
|
+
SignInAuthorizationParams,
|
|
43
|
+
SignOutParams,
|
|
44
|
+
SignInResponse,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export { SessionProviderProps }
|
|
48
|
+
// This behaviour mirrors the default behaviour for getting the site name that
|
|
49
|
+
// happens server side in server/index.js
|
|
50
|
+
// 1. An empty value is legitimate when the code is being invoked client side as
|
|
51
|
+
// relative URLs are valid in that context and so defaults to empty.
|
|
52
|
+
// 2. When invoked server side the value is picked up from an environment
|
|
53
|
+
// variable and defaults to 'http://localhost:3000'.
|
|
54
|
+
export const __MULGUARD: AuthClientConfig = {
|
|
55
|
+
baseUrl: parseUrl(process.env.MULGUARD_URL ?? process.env.NEXTAUTH_URL ?? process.env.AUTH_URL ?? process.env.VERCEL_URL).origin,
|
|
56
|
+
basePath: parseUrl(process.env.MULGUARD_URL ?? process.env.NEXTAUTH_URL ?? process.env.AUTH_URL).path,
|
|
57
|
+
baseUrlServer: parseUrl(
|
|
58
|
+
process.env.MULGUARD_URL_INTERNAL ??
|
|
59
|
+
process.env.NEXTAUTH_URL_INTERNAL ??
|
|
60
|
+
process.env.AUTH_URL ??
|
|
61
|
+
process.env.NEXTAUTH_URL ??
|
|
62
|
+
process.env.VERCEL_URL
|
|
63
|
+
).origin,
|
|
64
|
+
basePathServer: parseUrl(
|
|
65
|
+
process.env.MULGUARD_URL_INTERNAL ?? process.env.NEXTAUTH_URL_INTERNAL ?? process.env.AUTH_URL ?? process.env.NEXTAUTH_URL
|
|
66
|
+
).path,
|
|
67
|
+
_lastSync: 0,
|
|
68
|
+
_session: undefined,
|
|
69
|
+
_getSession: () => {},
|
|
70
|
+
}
|
|
71
|
+
// Backward compatibility
|
|
72
|
+
export const __NEXTAUTH = __MULGUARD
|
|
73
|
+
|
|
74
|
+
// https://github.com/mulguard/mulguard/pull/10762
|
|
75
|
+
let broadcastChannel: BroadcastChannel | null = null
|
|
76
|
+
|
|
77
|
+
function getNewBroadcastChannel() {
|
|
78
|
+
if (typeof BroadcastChannel === "undefined") {
|
|
79
|
+
return {
|
|
80
|
+
postMessage: () => {},
|
|
81
|
+
addEventListener: () => {},
|
|
82
|
+
removeEventListener: () => {},
|
|
83
|
+
name: "mulguard",
|
|
84
|
+
onmessage: null,
|
|
85
|
+
onmessageerror: null,
|
|
86
|
+
close: () => {},
|
|
87
|
+
dispatchEvent: () => false,
|
|
88
|
+
} satisfies BroadcastChannel
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return new BroadcastChannel("mulguard")
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function broadcast() {
|
|
95
|
+
if (broadcastChannel === null) {
|
|
96
|
+
broadcastChannel = getNewBroadcastChannel()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return broadcastChannel
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// TODO:
|
|
103
|
+
const logger: LoggerInstance = {
|
|
104
|
+
debug: console.debug,
|
|
105
|
+
error: console.error,
|
|
106
|
+
warn: console.warn,
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** @todo Document */
|
|
110
|
+
export type UpdateSession = (data?: any) => Promise<Session | null>
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* useSession() returns an object containing three things: a method called {@link UpdateSession|update}, `data` and `status`.
|
|
114
|
+
*/
|
|
115
|
+
export type SessionContextValue<R extends boolean = false> = R extends true
|
|
116
|
+
?
|
|
117
|
+
| { update: UpdateSession; data: Session; status: "authenticated" }
|
|
118
|
+
| { update: UpdateSession; data: null; status: "loading" }
|
|
119
|
+
:
|
|
120
|
+
| { update: UpdateSession; data: Session; status: "authenticated" }
|
|
121
|
+
| {
|
|
122
|
+
update: UpdateSession
|
|
123
|
+
data: null
|
|
124
|
+
status: "unauthenticated" | "loading"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const SessionContext = React.createContext?.<
|
|
128
|
+
SessionContextValue | undefined
|
|
129
|
+
>(undefined)
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* React Hook that gives you access to the logged in user's session data and lets you modify it.
|
|
133
|
+
*
|
|
134
|
+
* :::info
|
|
135
|
+
* `useSession` is for client-side use only and when using [Next.js App Router (`app/`)](https://nextjs.org/blog/next-13-4#nextjs-app-router) you should prefer the `auth()` export.
|
|
136
|
+
* :::
|
|
137
|
+
*/
|
|
138
|
+
export function useSession<R extends boolean>(
|
|
139
|
+
options?: UseSessionOptions<R>
|
|
140
|
+
): SessionContextValue<R> {
|
|
141
|
+
if (!SessionContext) {
|
|
142
|
+
throw new Error("React Context is unavailable in Server Components")
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// @ts-expect-error Satisfy TS if branch on line below
|
|
146
|
+
const value: SessionContextValue<R> = React.useContext(SessionContext)
|
|
147
|
+
if (!value && process.env.NODE_ENV !== "production") {
|
|
148
|
+
throw new Error(
|
|
149
|
+
"[next-auth]: `useSession` must be wrapped in a <SessionProvider />"
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const { required, onUnauthenticated } = options ?? {}
|
|
154
|
+
|
|
155
|
+
const requiredAndNotLoading = required && value.status === "unauthenticated"
|
|
156
|
+
|
|
157
|
+
React.useEffect(() => {
|
|
158
|
+
if (requiredAndNotLoading) {
|
|
159
|
+
const url = `${__NEXTAUTH.basePath}/signin?${new URLSearchParams({
|
|
160
|
+
error: "SessionRequired",
|
|
161
|
+
callbackUrl: window.location.href,
|
|
162
|
+
})}`
|
|
163
|
+
if (onUnauthenticated) onUnauthenticated()
|
|
164
|
+
else window.location.href = url
|
|
165
|
+
}
|
|
166
|
+
}, [requiredAndNotLoading, onUnauthenticated])
|
|
167
|
+
|
|
168
|
+
if (requiredAndNotLoading) {
|
|
169
|
+
return {
|
|
170
|
+
data: value.data,
|
|
171
|
+
update: value.update,
|
|
172
|
+
status: "loading",
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return value
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface GetSessionParams {
|
|
180
|
+
event?: "storage" | "timer" | "hidden" | string
|
|
181
|
+
triggerEvent?: boolean
|
|
182
|
+
broadcast?: boolean
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export async function getSession(params?: GetSessionParams) {
|
|
186
|
+
const session = await fetchData<Session>(
|
|
187
|
+
"session",
|
|
188
|
+
__NEXTAUTH,
|
|
189
|
+
logger,
|
|
190
|
+
params
|
|
191
|
+
)
|
|
192
|
+
if (params?.broadcast ?? true) {
|
|
193
|
+
// https://github.com/nextauthjs/next-auth/pull/11470
|
|
194
|
+
getNewBroadcastChannel().postMessage({
|
|
195
|
+
event: "session",
|
|
196
|
+
data: { trigger: "getSession" },
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
return session
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Returns the current Cross-Site Request Forgery Token (CSRF Token)
|
|
204
|
+
* required to make requests that changes state. (e.g. signing in or out, or updating the session).
|
|
205
|
+
*
|
|
206
|
+
* [CSRF Prevention: Double Submit Cookie](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#double-submit-cookie)
|
|
207
|
+
*/
|
|
208
|
+
export async function getCsrfToken() {
|
|
209
|
+
const response = await fetchData<{ csrfToken: string }>(
|
|
210
|
+
"csrf",
|
|
211
|
+
__NEXTAUTH,
|
|
212
|
+
logger
|
|
213
|
+
)
|
|
214
|
+
return response?.csrfToken ?? ""
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export async function getProviders() {
|
|
218
|
+
return fetchData<Record<ProviderId, ClientSafeProvider>>(
|
|
219
|
+
"providers",
|
|
220
|
+
__NEXTAUTH,
|
|
221
|
+
logger
|
|
222
|
+
)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Initiates a signin flow or sends the user to the signin page listing all possible providers.
|
|
227
|
+
* Handles CSRF protection.
|
|
228
|
+
*
|
|
229
|
+
* @note This method can only be used from Client Components ("use client" or Pages Router).
|
|
230
|
+
* For Server Actions, use the `signIn` method imported from the `auth` config.
|
|
231
|
+
*/
|
|
232
|
+
export async function signIn(
|
|
233
|
+
provider?: ProviderId,
|
|
234
|
+
options?: SignInOptions<true>,
|
|
235
|
+
authorizationParams?: SignInAuthorizationParams
|
|
236
|
+
): Promise<void>
|
|
237
|
+
export async function signIn(
|
|
238
|
+
provider?: ProviderId,
|
|
239
|
+
options?: SignInOptions<false>,
|
|
240
|
+
authorizationParams?: SignInAuthorizationParams
|
|
241
|
+
): Promise<SignInResponse>
|
|
242
|
+
export async function signIn<Redirect extends boolean = true>(
|
|
243
|
+
provider?: ProviderId,
|
|
244
|
+
options?: SignInOptions<Redirect>,
|
|
245
|
+
authorizationParams?: SignInAuthorizationParams
|
|
246
|
+
): Promise<SignInResponse | void> {
|
|
247
|
+
const { callbackUrl, ...rest } = options ?? {}
|
|
248
|
+
const {
|
|
249
|
+
redirect = true,
|
|
250
|
+
redirectTo = callbackUrl ?? window.location.href,
|
|
251
|
+
...signInParams
|
|
252
|
+
} = rest
|
|
253
|
+
|
|
254
|
+
const baseUrl = apiBaseUrl(__NEXTAUTH)
|
|
255
|
+
const providers = await getProviders()
|
|
256
|
+
|
|
257
|
+
if (!providers) {
|
|
258
|
+
const url = `${baseUrl}/error`
|
|
259
|
+
window.location.href = url
|
|
260
|
+
return // TODO: Return error if `redirect: false`
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (!provider || !providers[provider]) {
|
|
264
|
+
const url = `${baseUrl}/signin?${new URLSearchParams({
|
|
265
|
+
callbackUrl: redirectTo,
|
|
266
|
+
})}`
|
|
267
|
+
window.location.href = url
|
|
268
|
+
return // TODO: Return error if `redirect: false`
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const providerType = providers[provider].type
|
|
272
|
+
|
|
273
|
+
if (providerType === "webauthn") {
|
|
274
|
+
// TODO: Add docs link with explanation
|
|
275
|
+
throw new TypeError(
|
|
276
|
+
[
|
|
277
|
+
`Provider id "${provider}" refers to a WebAuthn provider.`,
|
|
278
|
+
'Please use `import { signIn } from "next-auth/webauthn"` instead.',
|
|
279
|
+
].join("\n")
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const signInUrl = `${baseUrl}/${
|
|
284
|
+
providerType === "credentials" ? "callback" : "signin"
|
|
285
|
+
}/${provider}`
|
|
286
|
+
|
|
287
|
+
const csrfToken = await getCsrfToken()
|
|
288
|
+
const res = await fetch(
|
|
289
|
+
`${signInUrl}?${new URLSearchParams(authorizationParams)}`,
|
|
290
|
+
{
|
|
291
|
+
method: "post",
|
|
292
|
+
headers: {
|
|
293
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
294
|
+
"X-Auth-Return-Redirect": "1",
|
|
295
|
+
},
|
|
296
|
+
body: new URLSearchParams({
|
|
297
|
+
...signInParams,
|
|
298
|
+
csrfToken,
|
|
299
|
+
callbackUrl: redirectTo,
|
|
300
|
+
}),
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
const data = await res.json()
|
|
305
|
+
|
|
306
|
+
if (redirect) {
|
|
307
|
+
const url = data.url ?? redirectTo
|
|
308
|
+
window.location.href = url
|
|
309
|
+
// If url contains a hash, the browser does not reload the page. We reload manually
|
|
310
|
+
if (url.includes("#")) window.location.reload()
|
|
311
|
+
return
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const error = new URL(data.url).searchParams.get("error") ?? undefined
|
|
315
|
+
const code = new URL(data.url).searchParams.get("code") ?? undefined
|
|
316
|
+
|
|
317
|
+
if (res.ok) {
|
|
318
|
+
await __NEXTAUTH._getSession({ event: "storage" })
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
error,
|
|
323
|
+
code,
|
|
324
|
+
status: res.status,
|
|
325
|
+
ok: res.ok,
|
|
326
|
+
url: error ? null : data.url,
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Initiate a signout, by destroying the current session.
|
|
332
|
+
* Handles CSRF protection.
|
|
333
|
+
*
|
|
334
|
+
* @note This method can only be used from Client Components ("use client" or Pages Router).
|
|
335
|
+
* For Server Actions, use the `signOut` method imported from the `auth` config.
|
|
336
|
+
*/
|
|
337
|
+
export async function signOut(options?: SignOutParams<true>): Promise<void>
|
|
338
|
+
export async function signOut(
|
|
339
|
+
options?: SignOutParams<false>
|
|
340
|
+
): Promise<SignOutResponse>
|
|
341
|
+
export async function signOut<R extends boolean = true>(
|
|
342
|
+
options?: SignOutParams<R>
|
|
343
|
+
): Promise<SignOutResponse | void> {
|
|
344
|
+
const {
|
|
345
|
+
redirect = true,
|
|
346
|
+
redirectTo = options?.callbackUrl ?? window.location.href,
|
|
347
|
+
} = options ?? {}
|
|
348
|
+
|
|
349
|
+
const baseUrl = apiBaseUrl(__NEXTAUTH)
|
|
350
|
+
const csrfToken = await getCsrfToken()
|
|
351
|
+
const res = await fetch(`${baseUrl}/signout`, {
|
|
352
|
+
method: "post",
|
|
353
|
+
headers: {
|
|
354
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
355
|
+
"X-Auth-Return-Redirect": "1",
|
|
356
|
+
},
|
|
357
|
+
body: new URLSearchParams({ csrfToken, callbackUrl: redirectTo }),
|
|
358
|
+
})
|
|
359
|
+
const data = await res.json()
|
|
360
|
+
|
|
361
|
+
broadcast().postMessage({ event: "session", data: { trigger: "signout" } })
|
|
362
|
+
|
|
363
|
+
if (redirect) {
|
|
364
|
+
const url = data.url ?? redirectTo
|
|
365
|
+
window.location.href = url
|
|
366
|
+
// If url contains a hash, the browser does not reload the page. We reload manually
|
|
367
|
+
if (url.includes("#")) window.location.reload()
|
|
368
|
+
return
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
await __NEXTAUTH._getSession({ event: "storage" })
|
|
372
|
+
|
|
373
|
+
return data
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* [React Context](https://react.dev/learn/passing-data-deeply-with-context) provider to wrap the app (`pages/`) to make session data available anywhere.
|
|
378
|
+
*
|
|
379
|
+
* When used, the session state is automatically synchronized across all open tabs/windows and they are all updated whenever they gain or lose focus
|
|
380
|
+
* or the state changes (e.g. a user signs in or out) when {@link SessionProviderProps.refetchOnWindowFocus} is `true`.
|
|
381
|
+
*
|
|
382
|
+
* :::info
|
|
383
|
+
* `SessionProvider` is for client-side use only and when using [Next.js App Router (`app/`)](https://nextjs.org/blog/next-13-4#nextjs-app-router) you should prefer the `auth()` export.
|
|
384
|
+
* :::
|
|
385
|
+
*/
|
|
386
|
+
export function SessionProvider(props: SessionProviderProps) {
|
|
387
|
+
if (!SessionContext) {
|
|
388
|
+
throw new Error("React Context is unavailable in Server Components")
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const { children, basePath, refetchInterval, refetchWhenOffline } = props
|
|
392
|
+
|
|
393
|
+
if (basePath) __NEXTAUTH.basePath = basePath
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* If session was `null`, there was an attempt to fetch it,
|
|
397
|
+
* but it failed, but we still treat it as a valid initial value.
|
|
398
|
+
*/
|
|
399
|
+
const hasInitialSession = props.session !== undefined
|
|
400
|
+
|
|
401
|
+
/** If session was passed, initialize as already synced */
|
|
402
|
+
__NEXTAUTH._lastSync = hasInitialSession ? now() : 0
|
|
403
|
+
|
|
404
|
+
const [session, setSession] = React.useState(() => {
|
|
405
|
+
if (hasInitialSession) __NEXTAUTH._session = props.session
|
|
406
|
+
return props.session
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
/** If session was passed, initialize as not loading */
|
|
410
|
+
const [loading, setLoading] = React.useState(!hasInitialSession)
|
|
411
|
+
|
|
412
|
+
React.useEffect(() => {
|
|
413
|
+
__NEXTAUTH._getSession = async ({ event } = {}) => {
|
|
414
|
+
try {
|
|
415
|
+
const storageEvent = event === "storage"
|
|
416
|
+
// We should always update if we don't have a client session yet
|
|
417
|
+
// or if there are events from other tabs/windows
|
|
418
|
+
if (storageEvent || __NEXTAUTH._session === undefined) {
|
|
419
|
+
__NEXTAUTH._lastSync = now()
|
|
420
|
+
__NEXTAUTH._session = await getSession({
|
|
421
|
+
broadcast: !storageEvent,
|
|
422
|
+
})
|
|
423
|
+
setSession(__NEXTAUTH._session)
|
|
424
|
+
return
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (
|
|
428
|
+
// If there is no time defined for when a session should be considered
|
|
429
|
+
// stale, then it's okay to use the value we have until an event is
|
|
430
|
+
// triggered which updates it
|
|
431
|
+
!event ||
|
|
432
|
+
// If the client doesn't have a session then we don't need to call
|
|
433
|
+
// the server to check if it does (if they have signed in via another
|
|
434
|
+
// tab or window that will come through as a "stroage" event
|
|
435
|
+
// event anyway)
|
|
436
|
+
__NEXTAUTH._session === null ||
|
|
437
|
+
// Bail out early if the client session is not stale yet
|
|
438
|
+
now() < __NEXTAUTH._lastSync
|
|
439
|
+
) {
|
|
440
|
+
return
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// An event or session staleness occurred, update the client session.
|
|
444
|
+
__NEXTAUTH._lastSync = now()
|
|
445
|
+
__NEXTAUTH._session = await getSession()
|
|
446
|
+
setSession(__NEXTAUTH._session)
|
|
447
|
+
} catch (error) {
|
|
448
|
+
logger.error(
|
|
449
|
+
new ClientSessionError((error as Error).message, error as any)
|
|
450
|
+
)
|
|
451
|
+
} finally {
|
|
452
|
+
setLoading(false)
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
__NEXTAUTH._getSession()
|
|
457
|
+
|
|
458
|
+
return () => {
|
|
459
|
+
__NEXTAUTH._lastSync = 0
|
|
460
|
+
__NEXTAUTH._session = undefined
|
|
461
|
+
__NEXTAUTH._getSession = () => {}
|
|
462
|
+
}
|
|
463
|
+
}, [])
|
|
464
|
+
|
|
465
|
+
React.useEffect(() => {
|
|
466
|
+
const handle = () => __NEXTAUTH._getSession({ event: "storage" })
|
|
467
|
+
// Listen for storage events and update session if event fired from
|
|
468
|
+
// another window (but suppress firing another event to avoid a loop)
|
|
469
|
+
// Fetch new session data but tell it to not to fire another event to
|
|
470
|
+
// avoid an infinite loop.
|
|
471
|
+
// Note: We could pass session data through and do something like
|
|
472
|
+
// `setData(message.data)` but that can cause problems depending
|
|
473
|
+
// on how the session object is being used in the client; it is
|
|
474
|
+
// more robust to have each window/tab fetch it's own copy of the
|
|
475
|
+
// session object rather than share it across instances.
|
|
476
|
+
broadcast().addEventListener("message", handle)
|
|
477
|
+
return () => broadcast().removeEventListener("message", handle)
|
|
478
|
+
}, [])
|
|
479
|
+
|
|
480
|
+
React.useEffect(() => {
|
|
481
|
+
const { refetchOnWindowFocus = true } = props
|
|
482
|
+
// Listen for when the page is visible, if the user switches tabs
|
|
483
|
+
// and makes our tab visible again, re-fetch the session, but only if
|
|
484
|
+
// this feature is not disabled.
|
|
485
|
+
const visibilityHandler = () => {
|
|
486
|
+
if (refetchOnWindowFocus && document.visibilityState === "visible")
|
|
487
|
+
__NEXTAUTH._getSession({ event: "visibilitychange" })
|
|
488
|
+
}
|
|
489
|
+
document.addEventListener("visibilitychange", visibilityHandler, false)
|
|
490
|
+
return () =>
|
|
491
|
+
document.removeEventListener("visibilitychange", visibilityHandler, false)
|
|
492
|
+
}, [props.refetchOnWindowFocus])
|
|
493
|
+
|
|
494
|
+
const isOnline = useOnline()
|
|
495
|
+
// TODO: Flip this behavior in next major version
|
|
496
|
+
const shouldRefetch = refetchWhenOffline !== false || isOnline
|
|
497
|
+
|
|
498
|
+
React.useEffect(() => {
|
|
499
|
+
if (refetchInterval && shouldRefetch) {
|
|
500
|
+
const refetchIntervalTimer = setInterval(() => {
|
|
501
|
+
if (__NEXTAUTH._session) {
|
|
502
|
+
__NEXTAUTH._getSession({ event: "poll" })
|
|
503
|
+
}
|
|
504
|
+
}, refetchInterval * 1000)
|
|
505
|
+
return () => clearInterval(refetchIntervalTimer)
|
|
506
|
+
}
|
|
507
|
+
}, [refetchInterval, shouldRefetch])
|
|
508
|
+
|
|
509
|
+
const value: any = React.useMemo(
|
|
510
|
+
() => ({
|
|
511
|
+
data: session,
|
|
512
|
+
status: loading
|
|
513
|
+
? "loading"
|
|
514
|
+
: session
|
|
515
|
+
? "authenticated"
|
|
516
|
+
: "unauthenticated",
|
|
517
|
+
async update(data: any) {
|
|
518
|
+
if (loading) return
|
|
519
|
+
setLoading(true)
|
|
520
|
+
const newSession = await fetchData<Session>(
|
|
521
|
+
"session",
|
|
522
|
+
__NEXTAUTH,
|
|
523
|
+
logger,
|
|
524
|
+
typeof data === "undefined"
|
|
525
|
+
? undefined
|
|
526
|
+
: { body: { csrfToken: await getCsrfToken(), data } }
|
|
527
|
+
)
|
|
528
|
+
setLoading(false)
|
|
529
|
+
if (newSession) {
|
|
530
|
+
setSession(newSession)
|
|
531
|
+
broadcast().postMessage({
|
|
532
|
+
event: "session",
|
|
533
|
+
data: { trigger: "getSession" },
|
|
534
|
+
})
|
|
535
|
+
}
|
|
536
|
+
return newSession
|
|
537
|
+
},
|
|
538
|
+
}),
|
|
539
|
+
[session, loading]
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
return (
|
|
543
|
+
// @ts-expect-error
|
|
544
|
+
<SessionContext.Provider value={value}>{children}</SessionContext.Provider>
|
|
545
|
+
)
|
|
546
|
+
}
|
package/src/webauthn.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { apiBaseUrl } from "./lib/client.js"
|
|
2
|
+
import { startAuthentication, startRegistration } from "@simplewebauthn/browser"
|
|
3
|
+
import { getCsrfToken, getProviders, __NEXTAUTH } from "./react.js"
|
|
4
|
+
|
|
5
|
+
import type { LoggerInstance } from "@mulverse/mulguard-core/types"
|
|
6
|
+
import type { WebAuthnOptionsResponseBody } from "@mulverse/mulguard-core/types"
|
|
7
|
+
import type { ProviderId } from "@mulverse/mulguard-core/providers"
|
|
8
|
+
import type {
|
|
9
|
+
AuthClientConfig,
|
|
10
|
+
SignInAuthorizationParams,
|
|
11
|
+
SignInOptions,
|
|
12
|
+
SignInResponse,
|
|
13
|
+
} from "./lib/client.js"
|
|
14
|
+
|
|
15
|
+
const logger: LoggerInstance = {
|
|
16
|
+
debug: console.debug,
|
|
17
|
+
error: console.error,
|
|
18
|
+
warn: console.warn,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Fetch webauthn options from server and prompt user for authentication or registration.
|
|
23
|
+
* Returns either the completed WebAuthn response or an error request.
|
|
24
|
+
*/
|
|
25
|
+
async function webAuthnOptions(
|
|
26
|
+
providerID: ProviderId,
|
|
27
|
+
nextAuthConfig: AuthClientConfig,
|
|
28
|
+
options?: Omit<SignInOptions, "redirect">
|
|
29
|
+
) {
|
|
30
|
+
const baseUrl = apiBaseUrl(nextAuthConfig)
|
|
31
|
+
|
|
32
|
+
// @ts-expect-error
|
|
33
|
+
const params = new URLSearchParams(options)
|
|
34
|
+
|
|
35
|
+
const optionsResp = await fetch(
|
|
36
|
+
`${baseUrl}/webauthn-options/${providerID}?${params}`
|
|
37
|
+
)
|
|
38
|
+
if (!optionsResp.ok) {
|
|
39
|
+
return { error: optionsResp }
|
|
40
|
+
}
|
|
41
|
+
const optionsData: WebAuthnOptionsResponseBody = await optionsResp.json()
|
|
42
|
+
|
|
43
|
+
if (optionsData.action === "authenticate") {
|
|
44
|
+
const webAuthnResponse = await startAuthentication(optionsData.options)
|
|
45
|
+
return { data: webAuthnResponse, action: "authenticate" }
|
|
46
|
+
} else {
|
|
47
|
+
const webAuthnResponse = await startRegistration(optionsData.options)
|
|
48
|
+
return { data: webAuthnResponse, action: "register" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Initiate a WebAuthn signin flow.
|
|
54
|
+
* @see https://authjs.dev/getting-started/authentication/webauthn
|
|
55
|
+
*/
|
|
56
|
+
export async function signIn(
|
|
57
|
+
provider?: ProviderId,
|
|
58
|
+
options?: SignInOptions<true>,
|
|
59
|
+
authorizationParams?: SignInAuthorizationParams
|
|
60
|
+
): Promise<void>
|
|
61
|
+
export async function signIn(
|
|
62
|
+
provider?: ProviderId,
|
|
63
|
+
options?: SignInOptions<false>,
|
|
64
|
+
authorizationParams?: SignInAuthorizationParams
|
|
65
|
+
): Promise<SignInResponse>
|
|
66
|
+
export async function signIn<Redirect extends boolean = true>(
|
|
67
|
+
provider?: ProviderId,
|
|
68
|
+
options?: SignInOptions<Redirect>,
|
|
69
|
+
authorizationParams?: SignInAuthorizationParams
|
|
70
|
+
): Promise<SignInResponse | void> {
|
|
71
|
+
const { callbackUrl, ...rest } = options ?? {}
|
|
72
|
+
const {
|
|
73
|
+
redirectTo = callbackUrl ?? window.location.href,
|
|
74
|
+
redirect = true,
|
|
75
|
+
...signInParams
|
|
76
|
+
} = rest
|
|
77
|
+
|
|
78
|
+
const baseUrl = apiBaseUrl(__NEXTAUTH)
|
|
79
|
+
const providers = await getProviders()
|
|
80
|
+
|
|
81
|
+
if (!providers) {
|
|
82
|
+
window.location.href = `${baseUrl}/error`
|
|
83
|
+
return // TODO: Return error if `redirect: false`
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (
|
|
87
|
+
!provider ||
|
|
88
|
+
!providers[provider] ||
|
|
89
|
+
providers[provider].type !== "webauthn"
|
|
90
|
+
) {
|
|
91
|
+
// TODO: Add docs link with explanation
|
|
92
|
+
throw new TypeError(
|
|
93
|
+
[
|
|
94
|
+
`Provider id "${provider}" does not refer to a WebAuthn provider.`,
|
|
95
|
+
'Please use `import { signIn } from "next-auth/react"` instead.',
|
|
96
|
+
].join("\n")
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const webAuthnBody: Record<string, unknown> = {}
|
|
101
|
+
const webAuthnResponse = await webAuthnOptions(
|
|
102
|
+
provider,
|
|
103
|
+
__NEXTAUTH,
|
|
104
|
+
signInParams
|
|
105
|
+
)
|
|
106
|
+
if (webAuthnResponse.error) {
|
|
107
|
+
logger.error(new Error(await webAuthnResponse.error.text()))
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
webAuthnBody.data = JSON.stringify(webAuthnResponse.data)
|
|
111
|
+
webAuthnBody.action = webAuthnResponse.action
|
|
112
|
+
|
|
113
|
+
const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}`
|
|
114
|
+
const res = await fetch(signInUrl, {
|
|
115
|
+
method: "post",
|
|
116
|
+
headers: {
|
|
117
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
118
|
+
"X-Auth-Return-Redirect": "1",
|
|
119
|
+
},
|
|
120
|
+
body: new URLSearchParams({
|
|
121
|
+
...signInParams,
|
|
122
|
+
...webAuthnBody,
|
|
123
|
+
csrfToken: await getCsrfToken(),
|
|
124
|
+
callbackUrl: redirectTo,
|
|
125
|
+
}),
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const data = await res.json()
|
|
129
|
+
|
|
130
|
+
if (redirect) {
|
|
131
|
+
const url = data.url ?? callbackUrl
|
|
132
|
+
window.location.href = url
|
|
133
|
+
// If url contains a hash, the browser does not reload the page. We reload manually
|
|
134
|
+
if (url.includes("#")) window.location.reload()
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const error = new URL(data.url).searchParams.get("error")
|
|
139
|
+
const code = new URL(data.url).searchParams.get("code")
|
|
140
|
+
|
|
141
|
+
if (res.ok) {
|
|
142
|
+
await __NEXTAUTH._getSession({ event: "storage" })
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
error,
|
|
147
|
+
code,
|
|
148
|
+
status: res.status,
|
|
149
|
+
ok: res.ok,
|
|
150
|
+
url: error ? null : data.url,
|
|
151
|
+
} as any
|
|
152
|
+
}
|
package/webauthn.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ProviderId } from "@mulverse/mulguard-core/providers";
|
|
2
|
+
import type { SignInAuthorizationParams, SignInOptions, SignInResponse } from "./lib/client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Initiate a WebAuthn signin flow.
|
|
5
|
+
* @see https://authjs.dev/getting-started/authentication/webauthn
|
|
6
|
+
*/
|
|
7
|
+
export declare function signIn(provider?: ProviderId, options?: SignInOptions<true>, authorizationParams?: SignInAuthorizationParams): Promise<void>;
|
|
8
|
+
export declare function signIn(provider?: ProviderId, options?: SignInOptions<false>, authorizationParams?: SignInAuthorizationParams): Promise<SignInResponse>;
|
|
9
|
+
//# sourceMappingURL=webauthn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webauthn.d.ts","sourceRoot":"","sources":["src/webauthn.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAEV,yBAAyB,EACzB,aAAa,EACb,cAAc,EACf,MAAM,iBAAiB,CAAA;AAuCxB;;;GAGG;AACH,wBAAsB,MAAM,CAC1B,QAAQ,CAAC,EAAE,UAAU,EACrB,OAAO,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,EAC7B,mBAAmB,CAAC,EAAE,yBAAyB,GAC9C,OAAO,CAAC,IAAI,CAAC,CAAA;AAChB,wBAAsB,MAAM,CAC1B,QAAQ,CAAC,EAAE,UAAU,EACrB,OAAO,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,EAC9B,mBAAmB,CAAC,EAAE,yBAAyB,GAC9C,OAAO,CAAC,cAAc,CAAC,CAAA"}
|