Skip to content

Commit

Permalink
refactor: finalize SDK refactoring
Browse files Browse the repository at this point in the history
BREAKING CHANGE: This change introduces a better SDK. As part of this change, several breaking changes with regards to the SDK have been introduced. We recommend reading this section carefully to understand the changes and how they might affect you.

Before, the SDK was structured into tags `public` and `admin`. This stems from the fact that we have two ports in Ory Kratos - one administrative and one public port.

While serves as a good overview when working with Ory Kratos, it does not express:

- What module the API belongs to (e.g. self-service, identity, ...)
- What maturity the API has (e.g. experimental, alpha, beta, ...)
- What version the API has (e.g. v0alpha0, v1beta0, ...)

This patch replaces the current `admin` and `public` tags with a versioned approach indicating the maturity of the API used. For example, `initializeSelfServiceSettingsForBrowsers` would no longer be under the `public` tag but instead under the `v0alpha1` tag:

```patch
import {
  Configuration,
- PublicApi
+ V0Alpha1
} from '@ory/kratos-client';

- const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public }));
+ const kratos = new V0Alpha1(new Configuration({ basePath: config.kratos.public }));
```

To avoid confusion when setting up the SDK, and potentially using the wrong endpoints in your codebase and ending up with strange 404 errors, Ory Kratos now redirects you to the correct port, given that `serve.(public|admin).base_url` are configured correctly. This is a significant improvement towards a more robust API experience!

Further, all administrative functions require, in the Ory SaaS, authorization using e.g. an Ory Personal Access Token. In the open source, we do not know what developers use to protect their APIs. As such, we believe that it is ok to have admin and public functions under one common API and differentiate with an `admin` prefix. Therefore, the following patches should be made in your codebase:

```patch
import {
- AdminApi,
+ V0Alpha1,
  Configuration
} from '@ory/kratos-client';

-const kratos = new AdminApi(new Configuration({ basePath: config.kratos.admin }));
+const kratos = new V0Alpha1(new Configuration({ basePath: config.kratos.admin }));

-kratos.createIdentity({
+kratos.adminCreateIdentity({
  schema_id: 'default',
  traits: { /* ... */ }
})
```

Further, we have introduced a [style guide for writing SDKs annotations](https://www.ory.sh/docs/ecosystem/contributing#openapi-spec-and-go-swagger) governing how naming conventions should be chosen.

We also streamlined how credentials are used. We now differentiate between:

- Per-request credentials such as the Ory Session Token / Cookie
    ```
    - public getSelfServiceRegistrationFlow(id: string, cookie?: string, options?: any) {}
    + public getSelfServiceSettingsFlow(id: string, xSessionToken?: string, cookie?: string, options?: any) {}
    ```
- Global credentials such as the Ory (SaaS) Personal Access Token.
    ```typescript
    const kratos = new V0Alpha0(new Configuration({ basePath: config.kratos.admin, accessToken: 'some-token' }));

    kratosAdmin.adminCreateIdentity({
      schema_id: 'default',
      traits: { /* ... */ },
    });
    ```

We hope you enjoy the vastly improved experience! There are still many things that we want to iterate on. For full context, we recommend reading the proposal and discussion around these changes at [kratos#1424](#1424).

Additionally, the Self-Service Error endpoint was updated. First, the endpoint `/self-service/errors` is now located at the public port only with the admin port redirecting to it. Second, the parameter `?error` was renamed to `?id` for better SDK compatibility. Parameter `?error` is still working but will be deprecated at some point. Third, the response no longer contains an error array in `errors` but instead just a single error under `error`:

```patch
{
  "id": "60208346-3a61-4880-96ae-0419cde8fca8",
- "errors": [{
+ "error": {
    "code": 404,
    "status": "Not Found",
    "reason": "foobar",
    "message": "The requested resource could not be found"
- }],
+ },
  "created_at": "2021-07-07T11:20:15.310506+02:00",
  "updated_at": "2021-07-07T11:20:15.310506+02:00"
}
```

Closes #1424
  • Loading branch information
aeneasr committed Jul 8, 2021
1 parent 7c431ed commit 5e9089f
Show file tree
Hide file tree
Showing 170 changed files with 18,370 additions and 8,853 deletions.
3 changes: 2 additions & 1 deletion .schema/openapi/gen.go.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
disallowAdditionalPropertiesIfNotPresent: true
packageName: client
generateInterfaces: false
generateInterfaces: true
isGoSubmodule: false
structPrefix: true
enumClassPrefix: true
5 changes: 1 addition & 4 deletions .schema/openapi/patches/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@
value: true

- op: replace
path: /components/schemas/selfServiceError/properties/errors/type
value: array
- op: replace
path: /components/schemas/selfServiceError/properties/errors/items
path: /components/schemas/selfServiceError/properties/error
value:
type: object

Expand Down
134 changes: 122 additions & 12 deletions .schema/openapi/patches/selfservice.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,134 @@
# Makes submitSelfServiceLoginFlowPayload polymorph
#- op: remove
# path: /components/schemas/submitSelfServiceLoginFlowBody/type
#- op: add
# path: /components/schemas/submitSelfServiceLoginFlowBody/oneOf
# value:
# - "$ref": "#/components/schemas/submitSelfServiceLoginFlowWithPasswordMethod"

# Makes submitSelfServiceRegistrationFlowPayload polymorph

# All modifications for the registration flow
- op: remove
path: /components/schemas/submitSelfServiceLoginFlow/type
path: /components/schemas/submitSelfServiceRegistrationFlowBody/type
- op: add
path: /components/schemas/submitSelfServiceRegistrationFlowWithPasswordMethodBody/properties/method/enum
value:
- password
- oidc
- op: add
path: /components/schemas/submitSelfServiceLoginFlow/oneOf
path: /components/schemas/submitSelfServiceRegistrationFlowBody/oneOf
value:
- "$ref": "#/components/schemas/submitSelfServiceLoginFlowWithPasswordMethod"
- "$ref": "#/components/schemas/submitSelfServiceRegistrationFlowWithPasswordMethodBody"
- op: add
path: /components/schemas/submitSelfServiceRegistrationFlowBody/discriminator
value:
propertyName: method
mapping:
password: "#/components/schemas/submitSelfServiceRegistrationFlowWithPasswordMethodBody"
oidc: "#/components/schemas/submitSelfServiceRegistrationFlowWithOidcMethodBody"
# end

# Makes submitSelfServiceRegistrationFlowPayload polymorph
# All modifications for the login flow
- op: remove
path: /components/schemas/submitSelfServiceLoginFlowBody/type
- op: add
path: /components/schemas/submitSelfServiceLoginFlowWithPasswordMethodBody/properties/method/enum
value:
- password
- oidc
- op: add
path: /components/schemas/submitSelfServiceLoginFlowBody/oneOf
value:
- "$ref": "#/components/schemas/submitSelfServiceLoginFlowWithPasswordMethodBody"
- op: add
path: /components/schemas/submitSelfServiceLoginFlowBody/discriminator
value:
propertyName: method
mapping:
password: "#/components/schemas/submitSelfServiceLoginFlowWithPasswordMethodBody"
oidc: "#/components/schemas/submitSelfServiceLoginFlowWithOidcMethodBody"
# end

# All modifications for the recovery flow
- op: remove
path: /components/schemas/submitSelfServiceRecoveryFlowBody/type
- op: add
path: /components/schemas/submitSelfServiceRecoveryFlowWithLinkMethodBody/properties/method/enum
value:
- password
- oidc
- op: add
path: /components/schemas/submitSelfServiceRecoveryFlowBody/oneOf
value:
- "$ref": "#/components/schemas/submitSelfServiceRecoveryFlowWithLinkMethodBody"
- op: add
path: /components/schemas/submitSelfServiceRecoveryFlowBody/discriminator
value:
propertyName: method
mapping:
link: "#/components/schemas/submitSelfServiceRecoveryFlowWithLinkMethodBody"
- op: add
path: /components/schemas/selfServiceRecoveryFlowState/enum
value:
- choose_method
- sent_email
- passed_challenge
# End

# All modifications for the verification flow
- op: remove
path: /components/schemas/submitSelfServiceRegistrationFlow/type
path: /components/schemas/submitSelfServiceVerificationFlowBody/type
- op: add
path: /components/schemas/submitSelfServiceVerificationFlowWithLinkMethodBody/properties/method/enum
value:
- password
- oidc
- op: add
path: /components/schemas/submitSelfServiceVerificationFlowBody/oneOf
value:
- "$ref": "#/components/schemas/submitSelfServiceVerificationFlowWithLinkMethodBody"
- op: add
path: /components/schemas/submitSelfServiceRegistrationFlow/oneOf
path: /components/schemas/submitSelfServiceVerificationFlowBody/discriminator
value:
- "$ref": "#/components/schemas/submitSelfServiceRegistrationFlowWithPasswordMethod"
propertyName: method
mapping:
link: "#/components/schemas/submitSelfServiceVerificationFlowWithLinkMethodBody"
- op: add
path: /components/schemas/selfServiceVerificationFlowState/enum
value:
- choose_method
- sent_email
- passed_challenge
# End


# Makes submitSelfServiceSettingsFlow polymorph

# All modifications for the settings flow
- op: remove
path: /components/schemas/submitSelfServiceSettingsFlow/type
path: /components/schemas/submitSelfServiceSettingsFlowBody/type
- op: add
path: /components/schemas/submitSelfServiceSettingsFlowWithPasswordMethodBody/properties/method/enum
value:
- password
- profile
- oidc
- op: add
path: /components/schemas/submitSelfServiceSettingsFlowBody/oneOf
value:
- "$ref": "#/components/schemas/submitSelfServiceSettingsFlowWithPasswordMethodBody"
- "$ref": "#/components/schemas/submitSelfServiceSettingsFlowWithProfileMethodBody"
- op: add
path: /components/schemas/submitSelfServiceSettingsFlowBody/discriminator
value:
propertyName: method
mapping:
password: "#/components/schemas/submitSelfServiceSettingsFlowWithPasswordMethodBody"
profile: "#/components/schemas/submitSelfServiceSettingsFlowWithProfileMethodBody"
oidc: "#/components/schemas/submitSelfServiceSettingsFlowWithOidcMethodBody"
- op: add
path: /components/schemas/submitSelfServiceSettingsFlow/oneOf
path: /components/schemas/selfServiceSettingsFlowState/enum
value:
- "$ref": "#/components/schemas/submitSelfServiceSettingsFlowWithPasswordMethod"
- "$ref": "#/components/schemas/submitSelfServiceSettingsFlowWithProfileMethod"
- show_form
- success
# end
2 changes: 1 addition & 1 deletion cmd/identities/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ WARNING: Importing credentials is not yet supported.`,

for src, i := range is {
err = ValidateIdentity(cmd, src, i, func(ctx context.Context, id string) (map[string]interface{}, *http.Response, error) {
return c.PublicApi.GetSchema(ctx, id).Execute()
return c.V0alpha1Api.GetJsonSchema(ctx, id).Execute()
})
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions cmd/identities/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Identities can be supplied via STD_IN or JSON files containing a single or an ar

for src, i := range is {
err = ValidateIdentity(cmd, src, i, func(ctx context.Context, id string) (map[string]interface{}, *http.Response, error) {
return c.PublicApi.GetSchema(ctx, id).Execute()
return c.V0alpha1Api.GetJsonSchema(ctx, id).Execute()
})
if err != nil {
return err
Expand All @@ -56,7 +56,7 @@ Identities can be supplied via STD_IN or JSON files containing a single or an ar

var schemas = make(map[string]*jsonschema.Schema)

const createIdentityPath = "api.json#/components/schemas/createIdentity"
const createIdentityPath = "api.json#/components/schemas/adminCreateIdentityBody"

type SchemaGetter = func(ctx context.Context, id string) (map[string]interface{}, *http.Response, error)

Expand Down
1 change: 1 addition & 0 deletions driver/registry_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func (m *RegistryDefault) RegisterPublicRoutes(ctx context.Context, router *x.Ro
func (m *RegistryDefault) RegisterAdminRoutes(ctx context.Context, router *x.RouterAdmin) {
m.RegistrationHandler().RegisterAdminRoutes(router)
m.LoginHandler().RegisterAdminRoutes(router)
m.LogoutHandler().RegisterAdminRoutes(router)
m.SchemaHandler().RegisterAdminRoutes(router)
m.SettingsHandler().RegisterAdminRoutes(router)
m.IdentityHandler().RegisterAdminRoutes(router)
Expand Down
2 changes: 1 addition & 1 deletion examples/go/pkg/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func SDKExitOnError(err error, res *http.Response) {
if err == nil {
return
}
body := x.MustReadAll(res.Body)
body, _ := json.MarshalIndent(json.RawMessage(x.MustReadAll(res.Body)), "", " ")
out, _ := json.MarshalIndent(err, "", " ")
fmt.Printf("%s\n\nAn error occurred: %+v\nbody: %s\n", out, err, body)
os.Exit(1)
Expand Down
38 changes: 26 additions & 12 deletions examples/go/pkg/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,44 @@ package pkg
import (
"context"
"log"
"strings"

"github.com/google/uuid"

ory "github.com/ory/kratos-client-go"
)

func RandomCredentials() (email, password string) {
email = "dev+" + uuid.New().String() + "@ory.sh"
password = strings.ReplaceAll(uuid.New().String(), "-", "")
return
}

// CreateIdentityWithSession creates an identity and an Ory Session Token for it.
func CreateIdentityWithSession(c *ory.APIClient) (*ory.Session, string) {
func CreateIdentityWithSession(c *ory.APIClient, email, password string) (*ory.Session, string) {
ctx := context.Background()

if email == "" {
email, _ = RandomCredentials()
}

if password == "" {
_, password = RandomCredentials()
}

// Initialize a registration flow
flow, _, err := c.PublicApi.InitializeSelfServiceRegistrationWithoutBrowser(ctx).Execute()
flow, _, err := c.V0alpha1Api.InitializeSelfServiceRegistrationFlowWithoutBrowser(ctx).Execute()
ExitOnError(err)

// Submit the registration flow
result, _, err := c.PublicApi.SubmitSelfServiceRegistrationFlow(ctx).Flow(flow.Id).SubmitSelfServiceRegistrationFlow(ory.SubmitSelfServiceRegistrationFlow{
&ory.SubmitSelfServiceRegistrationFlowWithPasswordMethod{
result, res, err := c.V0alpha1Api.SubmitSelfServiceRegistrationFlow(ctx).Flow(flow.Id).SubmitSelfServiceRegistrationFlowBody(
ory.SubmitSelfServiceRegistrationFlowWithPasswordMethodBodyAsSubmitSelfServiceRegistrationFlowBody(&ory.SubmitSelfServiceRegistrationFlowWithPasswordMethodBody{
Method: "password",
Password: ory.PtrString(uuid.New().String() + uuid.New().String()),
Traits: map[string]interface{}{
"email": "dev+" + uuid.New().String() + "@ory.sh",
},
},
}).Execute()
ExitOnError(err)
Password: password,
Traits: map[string]interface{}{"email": email},
}),
).Execute()
SDKExitOnError(err, res)

if result.Session == nil {
log.Fatalf("The server is expected to create sessions for new registrations.")
Expand All @@ -39,10 +52,11 @@ func CreateIdentityWithSession(c *ory.APIClient) (*ory.Session, string) {
func CreateIdentity(c *ory.APIClient) *ory.Identity {
ctx := context.Background()

email, _ := RandomCredentials()
identity, _, err := c.V0alpha1Api.AdminCreateIdentity(ctx).AdminCreateIdentityBody(ory.AdminCreateIdentityBody{
SchemaId: "default",
Traits: map[string]interface{}{
"email": "dev+" + uuid.New().String() + "@ory.sh",
"email": email,
}}).Execute()
ExitOnError(err)
return identity
Expand Down
2 changes: 1 addition & 1 deletion examples/go/selfservice/error/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestLogin(t *testing.T) {
func TestError(t *testing.T) {
publicURL, _ := testhelpers.StartE2EServer(t, "../../pkg/stub/kratos.yaml")
client = pkg.NewSDKForSelfHosted(publicURL)

Expand Down
28 changes: 0 additions & 28 deletions examples/go/selfservice/init/login/main.go

This file was deleted.

28 changes: 0 additions & 28 deletions examples/go/selfservice/init/recovery/main.go

This file was deleted.

19 changes: 0 additions & 19 deletions examples/go/selfservice/init/recovery/main_test.go

This file was deleted.

28 changes: 0 additions & 28 deletions examples/go/selfservice/init/registration/main.go

This file was deleted.

Loading

0 comments on commit 5e9089f

Please sign in to comment.