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

Add wrapper library for HTTP Managers #130

Merged
merged 17 commits into from
Jul 3, 2016
Merged
Show file tree
Hide file tree
Changes from 9 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
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,47 @@ Or by specifying the following flags:

You can do so by running `hydra host --force-dangerous-http`.

### How do I use it in my application?

Hydra already comes with HTTP Managers. You could use directly by importing the following or use the thin wrapper created in `ory-am/hydra/sdk`

**Manage OAuth Clients**
`ory-am/hydra/client.HTTPManager`

**Manage SSO Connections**
`ory-am/hydra/connection.HTTPManager`

**Manage Policies**
`ory-am/hydra/policy.HTTPManager`

**Manage JWK**
`ory-am/hydra/jwk.HTTPManager`

**Use Warden**
`ory-am/hydra/warden.HTTPWarden`

**To use SDK**

1. Connect to Hydra.
```
client, err := sdk.Connect(
sdk.ClientID("client-id"),
sdk.ClientSecret("client-secret"),
sdk.ClustURL("https://localhost:4444"),
)
```
2. Use the API

**OAuth Clients**: `client.Client`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add examples here? e.g.

// client, err := ...
oauth2Client, err := client.Client.GetClient("1234")


**SSO Connections**: `client.SSO`

**Policiess**: `client.Policy`

**JWK**: `client.JWK`

**Warden**: `client.Warden`

## Hall of Fame

A list of extraordinary contributors and [bug hunters](https://github.com/ory-am/hydra/issues/84).
Expand Down
129 changes: 129 additions & 0 deletions sdk/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Wraps hydra HTTP Manager's
package sdk

import (
"crypto/tls"
"net/http"
"net/url"
"os"

"github.com/ory-am/hydra/client"
"github.com/ory-am/hydra/connection"
"github.com/ory-am/hydra/jwk"
"github.com/ory-am/hydra/pkg"
"github.com/ory-am/hydra/policy"
"github.com/ory-am/hydra/warden"

"golang.org/x/net/context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/clientcredentials"
)

type Client struct {
http *http.Client
clusterURL *url.URL
clientID string
clientSecret string
skipSSL bool
scopes []string

credentials clientcredentials.Config

Client *client.HTTPManager
SSO *connection.HTTPManager
JWK *jwk.HTTPManager
Policies *policy.HTTPManager
Warden *warden.HTTPWarden
}

type option func(*Client) error

// default options for hydra client
var defaultOptions = []option{
ClusterURL(os.Getenv("HYDRA_CLUSTER_URL")),
ClientID(os.Getenv("HYDRA_CLIENT_ID")),
ClientSecret(os.Getenv("HYDRA_CLIENT_SECRET")),
Scopes("core", "hydra"),
}

// Connect instantiates a new client to communicate with Hydra
func Connect(opts ...option) (*Client, error) {
c := &Client{}

var err error
// apply default options
for _, opt := range defaultOptions {
err = opt(c)
if err != nil {
return nil, err
}
}

// override any default values with given options
for _, opt := range opts {
err = opt(c)
if err != nil {
return nil, err
}
}

c.credentials = clientcredentials.Config{
ClientID: c.clientID,
ClientSecret: c.clientSecret,
TokenURL: pkg.JoinURL(c.clusterURL, "oauth2/token").String(),
Scopes: c.scopes,
}

c.http = http.DefaultClient

if c.skipSSL {
c.http = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
}

err = c.authenticate()
if err != nil {
return nil, err
}

// initialize service endpoints
c.Client = &client.HTTPManager{
Endpoint: pkg.JoinURL(c.clusterURL, "/clients"),
Client: c.http,
}

c.SSO = &connection.HTTPManager{
Endpoint: pkg.JoinURL(c.clusterURL, "/connections"),
Client: c.http,
}

c.JWK = &jwk.HTTPManager{
Endpoint: pkg.JoinURL(c.clusterURL, "/keys"),
Client: c.http,
}

c.Policies = &policy.HTTPManager{
Endpoint: pkg.JoinURL(c.clusterURL, "/policies"),
Client: c.http,
}

c.Warden = &warden.HTTPWarden{
Client: c.http,
}

return c, nil
}

func (h *Client) authenticate() error {
ctx := context.WithValue(oauth2.NoContext, oauth2.HTTPClient, h.http)
_, err := h.credentials.Token(ctx)
if err != nil {
return err
}

h.http = h.credentials.Client(ctx)
return nil
}
75 changes: 75 additions & 0 deletions sdk/client_opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package sdk

import (
"io/ioutil"
"net/url"

"gopkg.in/yaml.v1"
)

func ClusterURL(urlStr string) option {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please document exported functions :)

return func(c *Client) error {
var err error
c.clusterURL, err = url.Parse(urlStr)
return err
}
}

func FromYAML(file string) option {
return func(c *Client) error {
var err error
var config = struct {
ClusterURL string `yaml:"cluster_url"`
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
}{}

data, err := ioutil.ReadFile(file)
if err != nil {
return err
}

err = yaml.Unmarshal(data, &config)
if err != nil {
return err
}

c.clusterURL, err = url.Parse(config.ClusterURL)
if err != nil {
return err
}

c.clientID = config.ClientID
c.clientSecret = config.ClientSecret

return nil
}
}

func ClientID(id string) option {
return func(c *Client) error {
c.clientID = id
return nil
}
}

func ClientSecret(secret string) option {
return func(c *Client) error {
c.clientSecret = secret
return nil
}
}

func SkipSSL() option {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you rename this to SkipTLSVerify, it's clearer then that the tls verification is disabled, not SSL in total

return func(c *Client) error {
c.skipSSL = true
return nil
}
}

func Scopes(scopes ...string) option {
return func(c *Client) error {
c.scopes = scopes
return nil
}
}