Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [AUTH-1403] Golang M2M Support #137

Merged
merged 4 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ linters-settings:
goimports:
local-prefixes: github.com/stytchauth/stytch-go/stytch
lll:
line-length: 150
line-length: 200
issues:
exclude-rules:
# Ignore comments with long urls
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ This client library supports all Stytch's live products:
- [x] [Time-based one-time passcodes (TOTPs)](https://stytch.com/docs/guides/totp/api)
- [x] [Crypto wallets](https://stytch.com/docs/guides/web3/api)
- [x] [Passwords](https://stytch.com/docs/guides/passwords/api)
- [x] [M2M](https://stytch.com/docs/api/m2m-client)


### Example usage
Expand Down
3 changes: 3 additions & 0 deletions stytch/b2b/b2bstytchapi/b2bstytchapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/stytchauth/stytch-go/v10/stytch"
"github.com/stytchauth/stytch-go/v10/stytch/b2b"
"github.com/stytchauth/stytch-go/v10/stytch/config"
"github.com/stytchauth/stytch-go/v10/stytch/consumer"
)

type Logger interface {
Expand All @@ -29,6 +30,7 @@ type API struct {
logger Logger

Discovery *b2b.DiscoveryClient
M2M *consumer.M2MClient
MagicLinks *b2b.MagicLinksClient
OAuth *b2b.OAuthClient
OTPs *b2b.OTPsClient
Expand Down Expand Up @@ -113,6 +115,7 @@ func NewClient(projectID string, secret string, opts ...Option) (*API, error) {
}

a.Discovery = b2b.NewDiscoveryClient(a.client)
a.M2M = consumer.NewM2MClient(a.client)
a.MagicLinks = b2b.NewMagicLinksClient(a.client)
a.OAuth = b2b.NewOAuthClient(a.client)
a.OTPs = b2b.NewOTPsClient(a.client)
Expand Down
48 changes: 43 additions & 5 deletions stytch/b2b/discovery/intermediatesessions/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,23 @@ package intermediatesessions
// !!!

import (
"github.com/stytchauth/stytch-go/v10/stytch/b2b/mfa"
"github.com/stytchauth/stytch-go/v10/stytch/b2b/organizations"
"github.com/stytchauth/stytch-go/v10/stytch/b2b/sessions"
)

// ExchangeParams: Request type for `IntermediateSessions.Exchange`.
type ExchangeParams struct {
// IntermediateSessionToken: The Intermediate Session Token. This token does not belong to a specific
// instance of a member, but may be exchanged for an existing Member Session or used to create a new
// organization.
// IntermediateSessionToken: The Intermediate Session Token. This token does not necessarily belong to a
// specific instance of a Member, but represents a bag of factors that may be converted to a member session.
// The token can be used with the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete an MFA
// flow;
// the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// to join a specific Organization that allows the factors represented by the intermediate session token;
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member.
IntermediateSessionToken string `json:"intermediate_session_token,omitempty"`
// OrganizationID: Globally unique UUID that identifies a specific Organization. The `organization_id` is
// critical to perform operations on an Organization, so be sure to preserve this value.
Expand All @@ -42,8 +50,21 @@ type ExchangeParams struct {
// delete a key, supply a null value. Custom claims made with reserved claims (`iss`, `sub`, `aud`,
// `exp`, `nbf`, `iat`, `jti`) will be ignored.
// Total custom claims size cannot exceed four kilobytes.
SessionCustomClaims map[string]any `json:"session_custom_claims,omitempty"`
Locale ExchangeRequestLocale `json:"locale,omitempty"`
SessionCustomClaims map[string]any `json:"session_custom_claims,omitempty"`
// Locale: (Coming Soon) If the Member needs to complete an MFA step, and the Member has a phone number,
// this endpoint will pre-emptively send a one-time passcode (OTP) to the Member's phone number. The locale
// argument will be used to determine which language to use when sending the passcode.
//
// Parameter is a [IETF BCP 47 language tag](https://www.w3.org/International/articles/language-tags/),
// e.g. `"en"`.
//
// Currently supported languages are English (`"en"`), Spanish (`"es"`), and Brazilian Portuguese
// (`"pt-br"`); if no value is provided, the copy defaults to English.
//
// Request support for additional languages
// [here](https://docs.google.com/forms/d/e/1FAIpQLScZSpAu_m2AmLXRT3F3kap-s_mcV6UTBitYn6CdyWP0-o7YjQ/viewform?usp=sf_link")!
//
Locale ExchangeRequestLocale `json:"locale,omitempty"`
}

// ExchangeResponse: Response type for `IntermediateSessions.Exchange`.
Expand All @@ -62,12 +83,29 @@ type ExchangeResponse struct {
Member organizations.Member `json:"member,omitempty"`
// Organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object).
Organization organizations.Organization `json:"organization,omitempty"`
// MemberAuthenticated: Indicates whether the Member is fully authenticated. If false, the Member needs to
// complete an MFA step to log in to the Organization.
MemberAuthenticated bool `json:"member_authenticated,omitempty"`
// IntermediateSessionToken: The returned Intermediate Session Token is identical to the one that was
// originally passed in to the request.
// The token can be used with the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete the
// MFA flow and log in to the Organization.
// It can also be used with the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// to join a different existing Organization,
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization.
IntermediateSessionToken string `json:"intermediate_session_token,omitempty"`
// StatusCode: The HTTP status code of the response. Stytch follows standard HTTP response status code
// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX
// are server errors.
StatusCode int32 `json:"status_code,omitempty"`
// MemberSession: The [Session object](https://stytch.com/docs/b2b/api/session-object).
MemberSession sessions.MemberSession `json:"member_session,omitempty"`
// MFARequired: (Coming Soon) Information about the MFA requirements of the Organization and the Member's
// options for fulfilling MFA.
MFARequired mfa.MfaRequired `json:"mfa_required,omitempty"`
}

type ExchangeRequestLocale string
Expand Down
60 changes: 53 additions & 7 deletions stytch/b2b/discovery/organizations/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ package organizations

import (
"github.com/stytchauth/stytch-go/v10/stytch/b2b/discovery"
"github.com/stytchauth/stytch-go/v10/stytch/b2b/mfa"
"github.com/stytchauth/stytch-go/v10/stytch/b2b/organizations"
"github.com/stytchauth/stytch-go/v10/stytch/b2b/sessions"
)

// CreateParams: Request type for `Organizations.Create`.
type CreateParams struct {
// IntermediateSessionToken: The Intermediate Session Token. This token does not belong to a specific
// instance of a member, but may be exchanged for an existing Member Session or used to create a new
// organization.
// IntermediateSessionToken: The Intermediate Session Token. This token does not necessarily belong to a
// specific instance of a Member, but represents a bag of factors that may be converted to a member session.
// The token can be used with the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete an MFA
// flow;
// the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// to join a specific Organization that allows the factors represented by the intermediate session token;
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member.
IntermediateSessionToken string `json:"intermediate_session_token,omitempty"`
// OrganizationName: The name of the Organization. If the name is not specified, a default name will be
// created based on the email used to initiate the discovery flow. If the email domain is a common email
Expand Down Expand Up @@ -113,14 +121,30 @@ type CreateParams struct {
// The list's accepted values are: `sso`, `magic_link`, `password`, `google_oauth`, and `microsoft_oauth`.
//
AllowedAuthMethods []string `json:"allowed_auth_methods,omitempty"`
MFAPolicy string `json:"mfa_policy,omitempty"`
// MFAPolicy: (Coming Soon) The setting that controls the MFA policy for all Members in the Organization.
// The accepted values are:
//
// `REQUIRED_FOR_ALL` – All Members within the Organization will be required to complete MFA every time
// they wish to log in.
//
// `OPTIONAL` – The default value. The Organization does not require MFA by default for all Members.
// Members will be required to complete MFA only if their `mfa_enrolled` status is set to true.
//
MFAPolicy string `json:"mfa_policy,omitempty"`
}

// ListParams: Request type for `Organizations.List`.
type ListParams struct {
// IntermediateSessionToken: The Intermediate Session Token. This token does not belong to a specific
// instance of a member, but may be exchanged for an existing Member Session or used to create a new
// organization.
// IntermediateSessionToken: The Intermediate Session Token. This token does not necessarily belong to a
// specific instance of a Member, but represents a bag of factors that may be converted to a member session.
// The token can be used with the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete an MFA
// flow;
// the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// to join a specific Organization that allows the factors represented by the intermediate session token;
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization and Member.
IntermediateSessionToken string `json:"intermediate_session_token,omitempty"`
// SessionToken: A secret token for a given Stytch Session.
SessionToken string `json:"session_token,omitempty"`
Expand All @@ -142,6 +166,20 @@ type CreateResponse struct {
SessionJWT string `json:"session_jwt,omitempty"`
// Member: The [Member object](https://stytch.com/docs/b2b/api/member-object).
Member organizations.Member `json:"member,omitempty"`
// MemberAuthenticated: Indicates whether the Member is fully authenticated. If false, the Member needs to
// complete an MFA step to log in to the Organization.
MemberAuthenticated bool `json:"member_authenticated,omitempty"`
// IntermediateSessionToken: The returned Intermediate Session Token is identical to the one that was
// originally passed in to the request.
// The token can be used with the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete the
// MFA flow and log in to the Organization.
// It can also be used with the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// to join a different existing Organization,
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to create a new Organization.
IntermediateSessionToken string `json:"intermediate_session_token,omitempty"`
// StatusCode: The HTTP status code of the response. Stytch follows standard HTTP response status code
// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX
// are server errors.
Expand All @@ -150,6 +188,9 @@ type CreateResponse struct {
MemberSession sessions.MemberSession `json:"member_session,omitempty"`
// Organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object).
Organization organizations.Organization `json:"organization,omitempty"`
// MFARequired: (Coming Soon) Information about the MFA requirements of the Organization and the Member's
// options for fulfilling MFA.
MFARequired mfa.MfaRequired `json:"mfa_required,omitempty"`
}

// ListResponse: Response type for `Organizations.List`.
Expand Down Expand Up @@ -181,4 +222,9 @@ type ListResponse struct {
// patterns, e.g. 2XX values equate to success, 3XX values are redirects, 4XX are client errors, and 5XX
// are server errors.
StatusCode int32 `json:"status_code,omitempty"`
// OrganizationIDHint: If the intermediate session token is associated with a specific Organization, that
// Organization ID will be returned here. The Organization ID will be null if the intermediate session
// token was generated by a email magic link discovery or OAuth discovery flow. If a session token or
// session JWT is provided, the Organization ID hint will be null.
OrganizationIDHint string `json:"organization_id_hint,omitempty"`
}
22 changes: 16 additions & 6 deletions stytch/b2b/discovery/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ import (

// DiscoveredOrganization:
type DiscoveredOrganization struct {
// MemberAuthenticated: Indicates whether or not the discovery magic link initiated session is valid for
// the organization's allowed auth method settings.
// If not, the member needs to perform additional authentication before logging in - such as password or
// SSO auth.
// MemberAuthenticated: Indicates whether the Member has all of the factors needed to fully authenticate to
// this Organization. If false, the Member may need to complete an MFA step or complete a different primary
// authentication flow. See the `primary_required` and `mfa_required` fields for more details on each.
MemberAuthenticated bool `json:"member_authenticated,omitempty"`
// Organization: The [Organization object](https://stytch.com/docs/b2b/api/organization-object).
Organization organizations.Organization `json:"organization,omitempty"`
// Membership: Information about the membership.
Membership Membership `json:"membership,omitempty"`
Membership Membership `json:"membership,omitempty"`
// PrimaryRequired: (Coming Soon) Information about the primary authentication requirements of the
// Organization.
PrimaryRequired PrimaryRequired `json:"primary_required,omitempty"`
MFARequired mfa.MfaRequired `json:"mfa_required,omitempty"`
// MFARequired: (Coming Soon) Information about the MFA requirements of the Organization and the Member's
// options for fulfilling MFA.
MFARequired mfa.MfaRequired `json:"mfa_required,omitempty"`
}

// Membership:
Expand All @@ -36,6 +39,13 @@ type Membership struct {
// null if one does not.
Member organizations.Member `json:"member,omitempty"`
}

// PrimaryRequired:
type PrimaryRequired struct {
// AllowedAuthMethods: If non-empty, indicates that the Organization restricts the authentication methods
// it allows for login (such as `sso` or `password`), and the end user must complete one of those
// authentication methods to log in. If empty, indicates that the Organization does not restrict the
// authentication method it allows for login, but the end user does not have any transferrable primary
// factors. Only email magic link and OAuth factors can be transferred between Organizations.
AllowedAuthMethods []string `json:"allowed_auth_methods,omitempty"`
}
12 changes: 12 additions & 0 deletions stytch/b2b/discovery_intermediatesessions.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ func NewDiscoveryIntermediateSessionsClient(c stytch.Client) *DiscoveryIntermedi
// This operation consumes the Intermediate Session.
//
// This endpoint can be used to accept invites and create new members via domain matching.
//
// (Coming Soon) If the Member is required to complete MFA to log in to the Organization, the returned
// value of `member_authenticated` will be `false`.
// The `intermediate_session_token` will not be consumed and instead will be returned in the response.
// The `intermediate_session_token` can be passed into the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete the
// MFA step and acquire a full member session.
// The `intermediate_session_token` can also be used with the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to join a different Organization or create a new one.
// The `session_duration_minutes` and `session_custom_claims` parameters will be ignored.
func (c *DiscoveryIntermediateSessionsClient) Exchange(
ctx context.Context,
body *intermediatesessions.ExchangeParams,
Expand Down
12 changes: 12 additions & 0 deletions stytch/b2b/discovery_organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ func NewDiscoveryOrganizationsClient(c stytch.Client) *DiscoveryOrganizationsCli
// This operation consumes the Intermediate Session.
//
// This endpoint can also be used to start an initial session for the newly created member and organization.
//
// (Coming Soon) If the new Organization is created with a `mfa_policy` of `REQUIRED_FOR_ALL`, the newly
// created Member will need to complete an MFA step to log in to the Organization.
// The `intermediate_session_token` will not be consumed and instead will be returned in the response.
// The `intermediate_session_token` can be passed into the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete the
// MFA step and acquire a full member session.
// The `intermediate_session_token` can also be used with the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to join a different Organization or create a new one.
// The `session_duration_minutes` and `session_custom_claims` parameters will be ignored.
func (c *DiscoveryOrganizationsClient) Create(
ctx context.Context,
body *organizations.CreateParams,
Expand Down
14 changes: 14 additions & 0 deletions stytch/b2b/magiclinks.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ func NewMagicLinksClient(c stytch.Client) *MagicLinksClient {
// Provide the `session_duration_minutes` parameter to set the lifetime of the session. If the
// `session_duration_minutes` parameter is not specified, a Stytch session will be created with a 60 minute
// duration.
//
// (Coming Soon) If the Member is required to complete MFA to log in to the Organization, the returned
// value of `member_authenticated` will be `false`, and an `intermediate_session_token` will be returned.
// The `intermediate_session_token` can be passed into the
// [OTP SMS Authenticate endpoint](https://stytch.com/docs/b2b/api/authenticate-otp-sms) to complete the
// MFA step and acquire a full member session.
// The `intermediate_session_token` can also be used with the
// [Exchange Intermediate Session endpoint](https://stytch.com/docs/b2b/api/exchange-intermediate-session)
// or the
// [Create Organization via Discovery endpoint](https://stytch.com/docs/b2b/api/create-organization-via-discovery) to join a different Organization or create a new one.
// The `session_duration_minutes` and `session_custom_claims` parameters will be ignored.
//
// If a valid `session_token` or `session_jwt` is passed in, the Member will not be required to complete an
// MFA step.
func (c *MagicLinksClient) Authenticate(
ctx context.Context,
body *magiclinks.AuthenticateParams,
Expand Down
Loading
Loading