• Stars
    star
    2,280
  • Rank 20,199 (Top 0.4 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created about 9 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A SDK for access control policies: authorization for the microservice and IoT age. Inspired by AWS IAM policies. Written for Go.

ORY Ladon - Policy-based Access Control

Join the chat at https://www.ory.sh/chat Join newsletter

Build Status Coverage Status Go Report Card GoDoc

Ladon is the serpent dragon protecting your resources.

Ladon is a library written in Go for access control policies, similar to Role Based Access Control or Access Control Lists. In contrast to ACL and RBAC you get fine-grained access control with the ability to answer questions in complex environments such as multi-tenant or distributed applications and large organizations. Ladon is inspired by AWS IAM Policies.

Ladon officially ships with an exemplary in-memory storage implementations. Community-supported adapters are available for CockroachDB.

Ladon is now considered stable.


ORY builds solutions for better internet security and accessibility. We have a couple more projects you might enjoy:

  • Hydra, a security-first open source OAuth2 and OpenID Connect server for new and existing infrastructures that uses Ladon for access control.
  • ORY Editor, an extensible, modern WYSI editor for the web written in React.
  • Fosite, an extensible security first OAuth 2.0 and OpenID Connect SDK for Go.
  • Dockertest: Write better integration tests with dockertest!

Table of Contents

Ladon utilizes ory-am/dockertest for tests. Please refer to ory-am/dockertest for more information of how to setup testing environment.

Installation

This library works with Go 1.11+.

export GO111MODULE=on
go get github.com/ory/ladon

Ladon uses semantic versioning and versions beginning with zero (0.1.2) might introduce backwards compatibility breaks with each minor version.

Concepts

Ladon is an access control library that answers the question:

Who is able to do what on something given some context

  • Who: An arbitrary unique subject name, for example "ken" or "printer-service.mydomain.com".
  • Able: The effect which can be either "allow" or "deny".
  • What: An arbitrary action name, for example "delete", "create" or "scoped:action:something".
  • Something: An arbitrary unique resource name, for example "something", "resources.articles.1234" or some uniform resource name like "urn:isbn:3827370191".
  • Context: The current context containing information about the environment such as the IP Address, request date, the resource owner name, the department ken is working in or any other information you want to pass along. (optional)

To decide what the answer is, Ladon uses policy documents which can be represented as JSON

{
  "description": "One policy to rule them all.",
  "subjects": ["users:<peter|ken>", "users:maria", "groups:admins"],
  "actions" : ["delete", "<create|update>"],
  "effect": "allow",
  "resources": [
    "resources:articles:<.*>",
    "resources:printer"
  ],
  "conditions": {
    "remoteIP": {
        "type": "CIDRCondition",
        "options": {
            "cidr": "192.168.0.1/16"
        }
    }
  }
}

and can answer access requests that look like:

{
  "subject": "users:peter",
  "action" : "delete",
  "resource": "resources:articles:ladon-introduction",
  "context": {
    "remoteIP": "192.168.0.5"
  }
}

However, Ladon does not come with a HTTP or server implementation. It does not restrict JSON either. We believe that it is your job to decide if you want to use Protobuf, RESTful, HTTP, AMQP, or some other protocol. It's up to you to write the server!

The following example should give you an idea what a RESTful flow could look like. Initially we create a policy by POSTing it to an artificial HTTP endpoint:

> curl \
      -X POST \
      -H "Content-Type: application/json" \
      -d@- \
      "https://my-ladon-implementation.localhost/policies" <<EOF
        {
          "description": "One policy to rule them all.",
          "subjects": ["users:<peter|ken>", "users:maria", "groups:admins"],
          "actions" : ["delete", "<create|update>"],
          "effect": "allow",
          "resources": [
            "resources:articles:<.*>",
            "resources:printer"
          ],
          "conditions": {
            "remoteIP": {
                "type": "CIDRCondition",
                "options": {
                    "cidr": "192.168.0.1/16"
                }
            }
          }
        }
  EOF

Then we test if "peter" (ip: "192.168.0.5") is allowed to "delete" the "ladon-introduction" article:

> curl \
      -X POST \
      -H "Content-Type: application/json" \
      -d@- \
      "https://my-ladon-implementation.localhost/warden" <<EOF
        {
          "subject": "users:peter",
          "action" : "delete",
          "resource": "resources:articles:ladon-introduction",
          "context": {
            "remoteIP": "192.168.0.5"
          }
        }
  EOF

{
    "allowed": true
}

Usage

We already discussed two essential parts of Ladon: policies and access control requests. Let's take a closer look at those two.

Policies

Policies are the basis for access control decisions. Think of them as a set of rules. In this library, policies are abstracted as the ladon.Policy interface, and Ladon comes with a standard implementation of this interface which is ladon.DefaultPolicy. Creating such a policy could look like:

import "github.com/ory/ladon"

var pol = &ladon.DefaultPolicy{
	// A required unique identifier. Used primarily for database retrieval.
	ID: "68819e5a-738b-41ec-b03c-b58a1b19d043",

	// A optional human readable description.
	Description: "something humanly readable",

	// A subject can be an user or a service. It is the "who" in "who is allowed to do what on something".
	// As you can see here, you can use regular expressions inside < >.
	Subjects: []string{"max", "peter", "<zac|ken>"},

	// Which resources this policy affects.
	// Again, you can put regular expressions in inside < >.
	Resources: []string{
            "myrn:some.domain.com:resource:123", "myrn:some.domain.com:resource:345",
            "myrn:something:foo:<.+>", "myrn:some.domain.com:resource:<(?!protected).*>",
            "myrn:some.domain.com:resource:<[[:digit:]]+>",
        },

	// Which actions this policy affects. Supports RegExp
	// Again, you can put regular expressions in inside < >.
	Actions: []string{"<create|delete>", "get"},

	// Should access be allowed or denied?
	// Note: If multiple policies match an access request, ladon.DenyAccess will always override ladon.AllowAccess
	// and thus deny access.
	Effect: ladon.AllowAccess,

	// Under which conditions this policy is "active".
	Conditions: ladon.Conditions{
		// In this example, the policy is only "active" when the requested subject is the owner of the resource as well.
		"resourceOwner": &ladon.EqualsSubjectCondition{},

		// Additionally, the policy will only match if the requests remote ip address matches address range 127.0.0.1/32
		"remoteIPAddress": &ladon.CIDRCondition{
			CIDR: "127.0.0.1/32",
		},
	},
}

Conditions

Conditions are functions returning true or false given a context. Because conditions implement logic, they must be programmed. Adding conditions to a policy consist of two parts, a key name and an implementation of ladon.Condition:

// StringEqualCondition is an exemplary condition.
type StringEqualCondition struct {
	Equals string `json:"equals"`
}

// Fulfills returns true if the given value is a string and is the
// same as in StringEqualCondition.Equals
func (c *StringEqualCondition) Fulfills(value interface{}, _ *ladon.Request) bool {
	s, ok := value.(string)

	return ok && s == c.Equals
}

// GetName returns the condition's name.
func (c *StringEqualCondition) GetName() string {
	return "StringEqualCondition"
}

var pol = &ladon.DefaultPolicy{
    // ...
    Conditions: ladon.Conditions{
        "some-arbitrary-key": &StringEqualCondition{
            Equals: "the-value-should-be-this"
        }
    },
}

The default implementation of Policy supports JSON un-/marshalling. In JSON, this policy would look like:

{
  "conditions": {
    "some-arbitrary-key": {
        "type": "StringEqualCondition",
        "options": {
            "equals": "the-value-should-be-this"
        }
    }
  }
}

As you can see, type is the value that StringEqualCondition.GetName() is returning and options is used to set the value of StringEqualCondition.Equals.

This condition is fulfilled by (we will cover the warden in the next section)

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
        "some-arbitrary-key": "the-value-should-be-this",
    },
}

but not by

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
        "some-arbitrary-key": "some other value",
    },
}

and neither by:

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
        "same value but other key": "the-value-should-be-this",
    },
}

Ladon ships with a couple of default conditions:

The CIDR condition matches CIDR IP Ranges. Using this condition would look like this in JSON:

{
    "conditions": {
        "remoteIPAddress": {
            "type": "CIDRCondition",
            "options": {
                "cidr": "192.168.0.1/16"
            }
        }
    }
}

and in Go:

var pol = &ladon.DefaultPolicy{
    Conditions: ladon.Conditions{
        "remoteIPAddress": &ladon.CIDRCondition{
            CIDR: "192.168.0.1/16",
        },
    },
}

In this case, we expect that the context of an access request contains a field "remoteIpAddress" matching the CIDR "192.168.0.1/16", for example "192.168.0.5".

Checks if the value passed in the access request's context is identical with the string that was given initially

var pol = &ladon.DefaultPolicy{
    Conditions: ladon.Conditions{
        "some-arbitrary-key": &ladon.StringEqualCondition{
            Equals: "the-value-should-be-this"
        }
    },
}

and would match in the following case:

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
         "some-arbitrary-key": "the-value-should-be-this",
    },
}

Checks if the boolean value passed in the access request's context is identical with the expected boolean value in the policy

var pol = &ladon.DefaultPolicy{
    Conditions: ladon.Conditions{
        "some-arbitrary-key": &ladon.BooleanCondition{
            BooleanValue: true,
        }
    },
}

and would match in the following case:

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
        "some-arbitrary-key": true,
    },
})

This condition type is particularly useful if you need to assert a policy dynamically on resources for multiple subjects. For example, consider if you wanted to enforce policy that only allows individuals that own a resource to view that resource. You'd have to be able to create a Ladon policy that permits access to every resource for every subject that enters your system.

With the Boolean Condition type, you can use conditional logic at runtime to create a match for a policy's condition.

Checks if the value passed in the access request's context matches the regular expression that was given initially

var pol = &ladon.DefaultPolicy{
    Conditions: ladon.Conditions{
      "some-arbitrary-key": &ladon.StringMatchCondition{
          Matches: "regex-pattern-here.+"
      }
    }
}

and would match in the following case:

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
          "some-arbitrary-key": "regex-pattern-here111"
    }
  }
})

Checks if the access request's subject is identical with the string that was given initially

var pol = &ladon.DefaultPolicy{
    Conditions: ladon.Conditions{
        "some-arbitrary-key": &ladon.EqualsSubjectCondition{}
    },
}

and would match

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Subject: "peter",
    Context: ladon.Context{
         "some-arbitrary-key": "peter",
    },
}

but not:

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Subject: "peter",
    Context: ladon.Context{
         "some-arbitrary-key": "max",
    },
}

Checks if the value passed in the access request's context contains two-element arrays and that both elements in each pair are equal.

var pol = &ladon.DefaultPolicy{
    Conditions: ladon.Conditions{
        "some-arbitrary-key": &ladon.StringPairsEqualCondition{}
    },
}

and would match

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
         "some-arbitrary-key": [
             ["some-arbitrary-pair-value", "some-arbitrary-pair-value"],
             ["some-other-arbitrary-pair-value", "some-other-arbitrary-pair-value"],
         ]
    },
}

but not:

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Context: ladon.Context{
         "some-arbitrary-key": [
             ["some-arbitrary-pair-value", "some-other-arbitrary-pair-value"],
         ]
    },
}

Checks if the string value passed in the access request's context is present in the resource string.

The Condition requires a value string and an optional delimiter (needs to match the resource string) to be passed.

A resource could for instance be: myrn:some.domain.com:resource:123 and myrn:some.otherdomain.com:resource:123 (the : is then considered a delimiter, and used by the condition to be able to separate the resource components from each other) to allow an action to the resources on myrn:some.otherdomain.com you could for instance create a resource condition with

{value: myrn:some.otherdomain.com, Delimiter: ":"}

alternatively:

{value: myrn:some.otherdomain.com}

The delimiter is optional but needed for the condition to be able to separate resource string components: i.e. to make sure the value foo:bar matches foo:bar but not foo:bara nor foo:bara:baz.

That is, a delimiter is necessary to separate:

{value: "myrn:fo", delimiter: ":"} from {value: "myrn:foo", delimiter: ":"} or {value: "myid:12"} from {value: "myid:123"}.

This condition is fulfilled by this (allow for all resources containing part:north):

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Resource: "rn:city:laholm:part:north"
    Context: ladon.Context{
      delimiter: ":",
      value: "part:north"
    },
}

or ( allow all resources with city:laholm)

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Resource: "rn:city:laholm:part:north"
    Context: ladon.Context{
      delimiter: ":",
      value: "city:laholm"
    },
}

but not (allow for all resources containing part:west, the resource does not contain part:west):

var err = warden.IsAllowed(&ladon.Request{
    // ...
    Resource: "rn:city:laholm:part:north"
    Context: ladon.Context{
      delimiter: ":",
      value: "part:west"
    },
}
Adding Custom Conditions

You can add custom conditions by appending it to ladon.ConditionFactories:

import "github.com/ory/ladon"

func main() {
    // ...

    ladon.ConditionFactories[new(CustomCondition).GetName()] = func() Condition {
        return new(CustomCondition)
    }

    // ...
}

Persistence

Obviously, creating such a policy is not enough. You want to persist it too. Ladon ships an interface ladon.Manager for this purpose. You have to implement that interface for persistence. An exemplary in-memory adapter can be found in ./manager/memory/manager_memory.go:

Let's take a look how to instantiate those:

In-Memory (officially supported)

import (
	"github.com/ory/ladon"
	manager "github.com/ory/ladon/manager/memory"
)


func main() {
	warden := &ladon.Ladon{
		Manager: manager.NewMemoryManager(),
	}
	err := warden.Manager.Create(pol)

    // ...
}

Access Control (Warden)

Now that we have defined our policies, we can use the warden to check if a request is valid. ladon.Ladon, which is the default implementation for the ladon.Warden interface defines ladon.Ladon.IsAllowed() which will return nil if the access request can be granted and an error otherwise.

import "github.com/ory/ladon"

func main() {
    // ...

    err := warden.IsAllowed(&ladon.Request{
        Subject: "peter",
        Action: "delete",
        Resource: "myrn:some.domain.com:resource:123",
        Context: ladon.Context{
            "ip": "127.0.0.1",
        },
    })
    if err != nil {
        log.Fatal("Access denied")
    }

    // ...
}

Audit Log (Warden)

In order to keep track of authorization grants and denials, it is possible to attach a ladon.AuditLogger. The provided ladon.AuditLoggerInfo outputs information about the policies involved when responding to authorization requests.

import "github.com/ory/ladon"
import manager "github.com/ory/ladon/manager/memory"

func main() {

    warden := ladon.Ladon{
        Manager: manager.NewMemoryManager(),
        AuditLogger: &ladon.AuditLoggerInfo{}
    }

    // ...

It will output to stderr by default.

Metrics

Ability to track authorization grants,denials and errors, it is possible to implement own interface for processing metrics.

type prometheusMetrics struct{}

func (mtr *prometheusMetrics) RequestDeniedBy(r ladon.Request, p ladon.Policy) {}
func (mtr *prometheusMetrics) RequestAllowedBy(r ladon.Request, policies ladon.Policies) {}
func (mtr *prometheusMetrics) RequestNoMatch(r ladon.Request) {}
func (mtr *prometheusMetrics) RequestProcessingError(r ladon.Request, err error) {}

func main() {

    warden := ladon.Ladon{
        Manager: manager.NewMemoryManager(),
        Metric:  &prometheusMetrics{},
    }

    // ...

Limitations

Ladon's limitations are listed here.

Regular expressions

Matching regular expressions has a complexity of O(n) (except lookahead/lookbehind assertions) and databases such as MySQL or Postgres can not leverage indexes when parsing regular expressions. Thus, there is considerable overhead when using regular expressions.

We have implemented various strategies for reducing policy matching time:

  1. An LRU cache is used for caching frequently compiled regular expressions. This reduces cpu complexity significantly for memory manager implementations.
  2. The SQL schema is 3NF normalized.
  3. Policies, subjects and actions are stored uniquely, reducing the total number of rows.
  4. Only one query per look up is executed.
  5. If no regular expression is used, a simple equal match is done in SQL back-ends.

You will get the best performance with the in-memory manager. The SQL adapters perform about 1000:1 compared to the in-memory solution. Please note that these tests where in laboratory environments with Docker, without an SSD, and single-threaded. You might get better results on your system. We are thinking about introducing simple cache strategies such as LRU with a maximum age to further reduce runtime complexity.

We are also considering to offer different matching strategies (e.g. wildcard match) in the future, which will perform better with SQL databases. If you have ideas or suggestions, leave us an issue.

Examples

Check out ladon_test.go which includes a couple of policies and tests cases. You can run the code with go test -run=TestLadon -v .

Good to know

  • All checks are case sensitive because subject values could be case sensitive IDs.
  • If ladon.Ladon is not able to match a policy with the request, it will default to denying the request and return an error.

Ladon does not use reflection for matching conditions to their appropriate structs due to security considerations.

Useful commands

Create mocks

mockgen -package ladon_test -destination manager_mock_test.go github.com/ory/ladon Manager

Third Party Libraries

By implementing the warden.Manager it is possible to create your own adapters to persist data in a datastore of your choice. Below are a list of third party implementations.

More Repositories

1

hydra

OpenID Certified™ OpenID Connect and OAuth Provider written in Go - cloud native, security-first, open source API security for your infrastructure. SDKs for any language. Works with Hardware Security Modules. Compatible with MITREid.
Go
14,588
star
2

kratos

Next-gen identity server (think Auth0, Okta, Firebase) with Ory-hardened authentication, MFA, FIDO2, TOTP, WebAuthn, profile management, identity schemas, social sign in, registration, account recovery, passwordless. Golang, headless, API-only - without templating or theming headaches. Available as a cloud service.
Go
8,361
star
3

keto

Open Source (Go) implementation of "Zanzibar: Google's Consistent, Global Authorization System". Ships gRPC, REST APIs, newSQL, and an easy and granular permission language. Supports ACL, RBAC, and other access models.
Go
4,745
star
4

dockertest

Write better integration tests! Dockertest helps you boot up ephermal docker images for your Go tests with minimal work.
Go
3,676
star
5

oathkeeper

A cloud native Identity & Access Proxy / API (IAP) and Access Control Decision API that authenticates, authorizes, and mutates incoming HTTP(s) requests. Inspired by the BeyondCorp / Zero Trust white paper. Written in Go.
Go
3,220
star
6

fosite

Extensible security first OAuth 2.0 and OpenID Connect SDK for Go.
Go
2,300
star
7

k8s

Kubernetes Helm Charts for the ORY ecosystem.
Mustache
330
star
8

kratos-selfservice-ui-node

TypeScript
278
star
9

hydra-login-consent-node

This is an ExpressJS reference implementation for the ORY Hydra User Login and Consent interface written in TypeScript and ExpressJS.
TypeScript
266
star
10

go-acc

Accurate Code Coverage reporting for Golang (Go)
Go
208
star
11

sdk

The place where ORY's SDKs are being auto-generated
PHP
137
star
12

docs

The Ory documentation
TypeScript
132
star
13

examples-archive

THIS REPOSITORY IS NOT UP TO DATE. Different docker-based examples for ORY's services (Hydra, Keto, Oathkeeper).
Shell
129
star
14

graceful

A best practice http server set up that supports graceful shutdown
Go
123
star
15

examples

A curated collection of examples and solutions created and maintained by the Ory Community.
JavaScript
103
star
16

x

Libraries used in the Ory ecosystem
Go
86
star
17

elements

Ory Elements is a component library that makes building login, registration and account pages for Ory a breeze. Check out the components library on Chromatic https://www.chromatic.com/library?appId=63b58e306cfd32348fa48d50
TypeScript
85
star
18

herodot

A lightweight Go library for writing responses and errors to HTTP
Go
82
star
19

kratos-selfservice-ui-react-nextjs

A full reference implementation for designing your own login, registration, recovery, verification, ... pages using Ory Kratos' APIs.
TypeScript
81
star
20

network

Ory runs a global end-to-end security infrastructure for humans, robots, and servers. We build and use open source software.
80
star
21

kratos-selfservice-ui-react-native

A reference implementation of an app using ORY Kratos for auth (login), sign up (registration), profile settings (update password), MFA/2FA, account recovery (password reset), and more for React Native. This repository is available as an expo template!
TypeScript
68
star
22

fosite-example

Go
66
star
23

kratos-client-go

Shell
55
star
24

cli

Create bulk action scripts, automate your tasks, manage your projects, and seamlessly interact with the Ory Network using the Ory command line interface (CLI).
Go
42
star
25

hydra-consent-app-go

A simple consent app for Hydra written in Go - for Hydra =< 1.0.0
Go
41
star
26

jobs

Want to build the next generation identity stack? You've come to the right place!
37
star
27

hydra-consent-app-express

A simple nodejs consent app based on express - for Hydra =< 1.0.0
JavaScript
37
star
28

hydra-client-go

Shell
34
star
29

oathkeeper-maester

Kuberenetes CRD Controller for Ory Oathkeeper. ⚠️ Maintained by the community, not an official Ory project!
Go
33
star
30

osin-storage

PostgreSQL storage backend for RangelReale osin OAuth2
Go
33
star
31

hydra-maester

Kuberenetes CRD Controller for Ory Hydra. ⚠️ Maintained by the community, not an official Ory project!
Go
32
star
32

web

www.ory.sh
TypeScript
25
star
33

hydra-client-java

Java
25
star
34

kratos-nextjs-react-example

Add login, registration, account recovery (password reset), account verification (email verification), social sign in, multi-factor authentication to your Next.js / React App using Ory!
TypeScript
25
star
35

status

DEPRECATED
Markdown
21
star
36

closed-reference-notifier

A GitHub action to open an issue when GitHub references in your code are closed.
TypeScript
20
star
37

hydra-js

DOES NOT WORK WITH VERSIONS > 0.10.0 - A simple library to help you build node-based identity providers that work with Hydra.
JavaScript
18
star
38

go-convenience

Well-tested helpers for dealing with daily problems in Go.
Go
18
star
39

defcon-30-ctf

Go
17
star
40

meta

A place where we plan and schedule our open source activities and track cross-project and ory-wide issues
Shell
17
star
41

redux-saga-fetch

A simple wrapper that reduces boilerplate code when using redux-saga in combination with async backend calls.
TypeScript
16
star
42

hydra-client-php

PHP
15
star
43

integrations

TypeScript
14
star
44

kratos-client-php

PHP
14
star
45

keto-client-go

Shell
14
star
46

build-buf-action

A GitHub action to build and lint protobuf using buildbuf
Shell
13
star
47

encrypt-dir

A very simple cli helper that encrypts files in directories using AES-GCM (128bit)
Go
13
star
48

summit

This repository holds all material related to the Ory Summit, specifically the presentations.
11
star
49

common

Ory's cross-project go libraries, intended for internal use.
Go
11
star
50

client-go

Shell
11
star
51

docusaurus-template

DEPRECATED
JavaScript
10
star
52

works

This repository shows examples of practical solutions using Ory projects and other OSS
Go
10
star
53

oathkeeper-client-go

Shell
10
star
54

ladon-community

Go
9
star
55

ci

Automation and robots for Ory's CI and CD pipelines
Shell
7
star
56

kratos-client-js

Autogenerated kratos SDK.
7
star
57

keto-client-java

Java
7
star
58

kratos-client-rust

Autogenerated kratos SDK.
Rust
7
star
59

kratos-client-java

Java
6
star
60

oathkeeper-client-php

PHP
6
star
61

keto-client-php

PHP
6
star
62

client-dotnet

Autogenerated client SDK.
C#
6
star
63

hydra-auth0-consent-sdk

A NodeJS library for working with Auth0 as an Identity Provider
JavaScript
6
star
64

kratos-client-ruby

Autogenerated kratos SDK.
Ruby
6
star
65

ory-config

A small Web App for configuring Ory systems built in VueJs 2.x
Vue
6
star
66

ory-sdk-go

Go
6
star
67

kratos-client-dart

Autogenerated kratos SDK.
Dart
5
star
68

ory-sdk-archive

Shell
5
star
69

pagination

Go
5
star
70

client-php

PHP
5
star
71

milestone-action

JavaScript
5
star
72

eslint-config-ory-am-react

The ESLint configuration used by Ory (React specific)
JavaScript
5
star
73

themes

TypeScript
5
star
74

open-source-support

Are you looking for help above and beyond our community self service support?
5
star
75

kratos-maester

5
star
76

hydra-client-dart

Autogenerated hydra SDK.
Dart
4
star
77

hydra-client-js

Autogenerated hydra SDK.
4
star
78

homebrew-tap

Location for all of Ory's homebrew packages
Ruby
4
star
79

label-sync-action

JavaScript
4
star
80

summit-platform

TypeScript
4
star
81

kratos-client-python

Autogenerated kratos SDK.
Python
4
star
82

keto-maester

4
star
83

metrics-middleware

A simple metrics middleware for segment.io
Go
4
star
84

sdk-js

JavaScript
4
star
85

client-java

Java
4
star
86

client-js

Autogenerated client SDK.
4
star
87

eslint-config-ory-am

The ESLint configuration used by Ory
JavaScript
3
star
88

changelog

Ory Changelog Generator
JavaScript
3
star
89

scoop

3
star
90

ory-client-go

3
star
91

slack-invite

3
star
92

oathkeeper-client-dotnet

Autogenerated oathkeeper SDK.
C#
3
star
93

oathkeeper-client-js

Autogenerated oathkeeper SDK.
3
star
94

hydra-oracle-plugin

Go
3
star
95

hydra-client-ruby

Autogenerated hydra SDK.
Ruby
3
star
96

hydra-client-rust

Autogenerated hydra SDK.
Rust
3
star
97

release

Release infrastructure for ORY and related components
HTML
3
star
98

hydra-client-dotnet

Autogenerated hydra SDK.
C#
3
star
99

homebrew-kratos

Ruby
3
star
100

keto-client-python

Autogenerated keto SDK.
3
star