Skip to content

Commit

Permalink
feat: added workos provider
Browse files Browse the repository at this point in the history
  • Loading branch information
panbanda committed Mar 19, 2024
1 parent fa5a112 commit 06e5637
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 5 deletions.
11 changes: 9 additions & 2 deletions .schemastore/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@
},
"provider": {
"title": "Provider",
"description": "Can be one of github, github-app, gitlab, generic, google, microsoft, discord, slack, facebook, auth0, vk, yandex, apple, spotify, netid, dingtalk, patreon.",
"description": "Can be one of github, github-app, gitlab, generic, google, microsoft, discord, slack, facebook, auth0, vk, yandex, apple, spotify, netid, dingtalk, patreon, workos.",
"type": "string",
"enum": [
"github",
Expand All @@ -436,7 +436,8 @@
"dingtalk",
"patreon",
"linkedin",
"lark"
"lark",
"workos"
],
"examples": ["google"]
},
Expand Down Expand Up @@ -509,6 +510,12 @@
"type": "string",
"examples": ["KP76DQS54M"]
},
"workos_organization_id": {
"title": "WorkOS Organization ID",
"description": "WorkOS Organization ID needed for performing SSO authorizations",
"type": "string",
"examples": ["org_000000000000000000000"]
},
"apple_private_key_id": {
"title": "Apple Private Key Identifier",
"description": "Sign In with Apple Private Key Identifier needed for generating a JWT token for client secret",
Expand Down
9 changes: 8 additions & 1 deletion embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@
},
"provider": {
"title": "Provider",
"description": "Can be one of github, github-app, gitlab, generic, google, microsoft, discord, slack, facebook, auth0, vk, yandex, apple, spotify, netid, dingtalk, patreon.",
"description": "Can be one of github, github-app, gitlab, generic, google, microsoft, discord, slack, facebook, auth0, vk, yandex, apple, spotify, netid, dingtalk, patreon, workos.",
"type": "string",
"enum": [
"github",
Expand All @@ -438,6 +438,7 @@
"linkedin",
"linkedin_v2",
"lark",
"workos",
"x"
],
"examples": ["google"]
Expand Down Expand Up @@ -511,6 +512,12 @@
"type": "string",
"examples": ["KP76DQS54M"]
},
"workos_organization_id": {
"title": "WorkOS Organization ID",
"description": "WorkOS Organization ID needed for performing SSO authorizations",
"type": "string",
"examples": ["org_000000000000000000000"]
},
"apple_private_key_id": {
"title": "Apple Private Key Identifier",
"description": "Sign In with Apple Private Key Identifier needed for generating a JWT token for client secret",
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ require (
github.com/golang/glog v1.1.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.0 // indirect
github.com/google/pprof v0.0.0-20221010195024-131d412537ea // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
Expand Down Expand Up @@ -332,11 +332,14 @@ require (
github.com/coreos/go-oidc/v3 v3.9.0
github.com/dghubble/oauth1 v0.7.2
github.com/lestrrat-go/jwx/v2 v2.0.19
github.com/motemen/go-loghttp v0.0.0-20231107055348-29ae44b293f4
github.com/workos/workos-go/v3 v3.2.0
)

require (
github.com/jackc/puddle/v2 v2.1.2 // indirect
github.com/lestrrat-go/httprc v1.0.4 // indirect
github.com/motemen/go-nuts v0.0.0-20220604134737-2658d0104f31 // indirect
github.com/segmentio/asm v1.2.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
)
12 changes: 11 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -415,8 +416,9 @@ github.com/google/go-github/v38 v38.1.0 h1:C6h1FkaITcBFK7gAmq4eFzt6gbhEhk7L5z6R3
github.com/google/go-github/v38 v38.1.0/go.mod h1:cStvrz/7nFr0FoENgG6GLbp53WaelXucT+BBz/3VKx4=
github.com/google/go-jsonnet v0.20.0 h1:WG4TTSARuV7bSm4PMB4ohjxe33IHT5WVTrJSU33uT4g=
github.com/google/go-jsonnet v0.20.0/go.mod h1:VbgWF9JX7ztlv770x/TolZNGGFfiHEVx9G6ca2eUmeA=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
Expand Down Expand Up @@ -777,6 +779,10 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6f
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/motemen/go-loghttp v0.0.0-20231107055348-29ae44b293f4 h1:WLWwzjax2/L5NAQul9bdk1EAP0+YGnAzJBJ/LzL8Dgs=
github.com/motemen/go-loghttp v0.0.0-20231107055348-29ae44b293f4/go.mod h1:ykaRC7b5xKciHTUFZ60bbsOojQAkCmmehBNbBWeIz1Y=
github.com/motemen/go-nuts v0.0.0-20220604134737-2658d0104f31 h1:lQ+0Zt2gm+w5+9iaBWKdJXC/gMrWjHhNbw9ts/9rSZ4=
github.com/motemen/go-nuts v0.0.0-20220604134737-2658d0104f31/go.mod h1:vkBO+XDNzovo+YLBpUod2SFvuWLObXlERnfj99RP3rU=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
Expand Down Expand Up @@ -902,6 +908,7 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/samber/lo v1.37.0 h1:XjVcB8g6tgUp8rsPsJ2CvhClfImrpL04YpQHXeHPhRw=
github.com/samber/lo v1.37.0/go.mod h1:9vaz2O4o8oOnK23pd2TrXufcbdbJIa3b6cstBWKpopA=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
Expand Down Expand Up @@ -1007,6 +1014,8 @@ github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJ
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/workos/workos-go/v3 v3.2.0 h1:U+PfTR/cHmJo4BbkGI7rISU7xU5DgUSAi/+/2oqa8V8=
github.com/workos/workos-go/v3 v3.2.0/go.mod h1:SUdYqICB2LG2G2UMMNI2EcBYX9OdpzgpNYlW6k0JML4=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
Expand Down Expand Up @@ -1221,6 +1230,7 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210810183815-faf39c7919d5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down
5 changes: 5 additions & 0 deletions selfservice/strategy/oidc/provider_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type Configuration struct {
// - dingtalk
// - linkedin
// - patreon
// - workos
Provider string `json:"provider"`

// Label represents an optional label which can be used in the UI generation.
Expand Down Expand Up @@ -81,6 +82,9 @@ type Configuration struct {
// is used to generate `client_secret`
TeamId string `json:"apple_team_id"`

// OrgID is the WorkOS Organization ID that's needed for the `workos` `provider` to work.
WorkOSOrganizationId string `json:"workos_organization_id"`

// PrivateKeyId is the private Apple key identifier. Keys can be generated via developer.apple.com.
// This key should be generated with the `Sign In with Apple` option checked.
// This is needed when `provider` is set to `apple`
Expand Down Expand Up @@ -161,6 +165,7 @@ var supportedProviders = map[string]func(config *Configuration, reg Dependencies
"linkedin_v2": NewProviderLinkedInV2,
"patreon": NewProviderPatreon,
"lark": NewProviderLark,
"workos": NewProviderWorkOS,
"x": NewProviderX,
}

Expand Down
86 changes: 86 additions & 0 deletions selfservice/strategy/oidc/provider_workos.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright © 2023 Ory Corp
// SPDX-License-Identifier: Apache-2.0

package oidc

import (
"context"
"net/url"

"github.com/pkg/errors"
"golang.org/x/oauth2"

"github.com/workos/workos-go/v3/pkg/sso"

_ "github.com/motemen/go-loghttp/global"

"github.com/ory/herodot"
)

type ProviderWorkOS struct {
config *Configuration
reg Dependencies
ssoClient *sso.Client
}

func NewProviderWorkOS(
config *Configuration,
reg Dependencies,
) Provider {
return &ProviderWorkOS{
config: config,
reg: reg,
ssoClient: &sso.Client{
APIKey: config.ClientSecret,
ClientID: config.ClientID,
},

Check warning on line 36 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L29-L36

Added lines #L29 - L36 were not covered by tests
}
}

func (g *ProviderWorkOS) Config() *Configuration {
return g.config

Check warning on line 41 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L40-L41

Added lines #L40 - L41 were not covered by tests
}

func (g *ProviderWorkOS) oauth2(ctx context.Context) *oauth2.Config {
endpoint := oauth2.Endpoint{
AuthURL: "https://api.workos.com/sso/authorize?organization=" + g.config.WorkOSOrganizationId,
TokenURL: "https://api.workos.com/sso/token",

Check warning on line 47 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L44-L47

Added lines #L44 - L47 were not covered by tests
}

return &oauth2.Config{
ClientID: g.config.ClientID,
ClientSecret: g.config.ClientSecret,
Endpoint: endpoint,
RedirectURL: g.config.Redir(g.reg.Config().OIDCRedirectURIBase(ctx)),

Check warning on line 54 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L50-L54

Added lines #L50 - L54 were not covered by tests
}
}

func (g *ProviderWorkOS) OAuth2(ctx context.Context) (*oauth2.Config, error) {
return g.oauth2(ctx), nil

Check warning on line 59 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L58-L59

Added lines #L58 - L59 were not covered by tests
}

func (g *ProviderWorkOS) AuthCodeURLOptions(r ider) []oauth2.AuthCodeOption {
return []oauth2.AuthCodeOption{}

Check warning on line 63 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L62-L63

Added lines #L62 - L63 were not covered by tests
}

func (g *ProviderWorkOS) Claims(ctx context.Context, exchange *oauth2.Token, query url.Values) (*Claims, error) {
profile, err := g.ssoClient.GetProfile(
ctx,
sso.GetProfileOpts{
AccessToken: exchange.AccessToken,
},
)
if err != nil {
return nil, errors.WithStack(herodot.ErrInternalServerError.WithReasonf("%s", err))

Check warning on line 74 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L66-L74

Added lines #L66 - L74 were not covered by tests
}

claims := &Claims{
Subject: profile.ID,
GivenName: profile.FirstName,
FamilyName: profile.LastName,
Email: profile.Email,
Issuer: "https://api.workos.com/sso/authorize?organization=" + g.config.WorkOSOrganizationId,

Check warning on line 82 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L77-L82

Added lines #L77 - L82 were not covered by tests
}

return claims, nil

Check warning on line 85 in selfservice/strategy/oidc/provider_workos.go

View check run for this annotation

Codecov / codecov/patch

selfservice/strategy/oidc/provider_workos.go#L85

Added line #L85 was not covered by tests
}
6 changes: 6 additions & 0 deletions test/e2e/cypress/support/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ export type SelfServiceOIDCProvider = SelfServiceOIDCProvider1 & {
microsoft_tenant?: AzureADTenant
subject_source?: MicrosoftSubjectSource
apple_team_id?: AppleDeveloperTeamID
workos_organization_id?: WorkOSOrganizationID
apple_private_key_id?: ApplePrivateKeyIdentifier
apple_private_key?: ApplePrivateKey
requested_claims?: OpenIDConnectClaims
Expand Down Expand Up @@ -231,6 +232,7 @@ export type Provider =
| "patreon"
| "linkedin"
| "lark"
| "workos"
export type OptionalStringWhichWillBeUsedWhenGeneratingLabelsForUIButtons =
string
/**
Expand All @@ -245,6 +247,10 @@ export type AzureADTenant = string
* Controls which source the subject identifier is taken from by microsoft provider. If set to `userinfo` (the default) then the identifier is taken from the `sub` field of OIDC ID token or data received from `/userinfo` standard OIDC endpoint. If set to `me` then the `id` field of data structure received from `https://graph.microsoft.com/v1.0/me` is taken as an identifier.
*/
export type MicrosoftSubjectSource = "userinfo" | "me"
/**
* WorkOS Organization ID
*/
export type WorkOSOrganizationID = string
/**
* Apple Developer Team ID needed for generating a JWT token for client secret
*/
Expand Down

0 comments on commit 06e5637

Please sign in to comment.