Code Monkey home page Code Monkey logo

go-oauth2-server's Introduction

Go OAuth2 Server

This service implements OAuth 2.0 specification. Excerpts from the specification are included in this README file to describe different grant types. Please read the full spec for more detailed information.

Travis Status for RichardKnop/go-oauth2-server godoc for RichardKnop/go-oauth2-server codecov for RichardKnop/go-oauth2-server

Sourcegraph for RichardKnop/go-oauth2-server Donate Bitcoin


OAuth 2.0

Client Authentication

http://tools.ietf.org/html/rfc6749#section-3.2.1

Clients must authenticate with client credentials (client ID and secret) when issuing requests to /v1/oauth/tokens endpoint. Basic HTTP authentication should be used.

Grant Types

Authorization Code

http://tools.ietf.org/html/rfc6749#section-4.1

The authorization code grant type is used to obtain both access tokens and refresh tokens and is optimized for confidential clients. Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.

+----------+
| Resource |
|   Owner  |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier      +---------------+
|         -+----(A)-- & Redirection URI ---->|               |
|  User-   |                                 | Authorization |
|  Agent  -+----(B)-- User authenticates --->|     Server    |
|          |                                 |               |
|         -+----(C)-- Authorization Code ---<|               |
+-|----|---+                                 +---------------+
  |    |                                         ^      v
 (A)  (C)                                        |      |
  |    |                                         |      |
  ^    v                                         |      |
+---------+                                      |      |
|         |>---(D)-- Authorization Code ---------'      |
|  Client |          & Redirection URI                  |
|         |                                             |
|         |<---(E)----- Access Token -------------------'
+---------+       (w/ Optional Refresh Token)

The client initiates the flow by directing the resource owner's user-agent to the authorization endpoint. The client includes its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted (or denied).

http://localhost:8080/web/authorize?client_id=test_client_1&redirect_uri=https%3A%2F%2Fwww.example.com&response_type=code&state=somestate&scope=read_write

The authorization server authenticates the resource owner (via the user-agent).

Log In page screenshot

The authorization server then establishes whether the resource owner grants or denies the client's access request.

Authorize page screenshot

If the request fails due to a missing, invalid, or mismatching redirection URI, or if the client identifier is missing or invalid, the authorization server SHOULD inform the resource owner of the error and MUST NOT automatically redirect the user-agent to the invalid redirection URI.

If the resource owner denies the access request or if the request fails for reasons other than a missing or invalid redirection URI, the authorization server informs the client by adding the error parameter to the query component of the redirection URI.

https://www.example.com/?error=access_denied&state=somestate

Assuming the resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI provided earlier (in the request or during client registration). The redirection URI includes an authorization code and any local state provided by the client earlier.

https://www.example.com/?code=7afb1c55-76e4-4c76-adb7-9d657cb47a27&state=somestate

The client requests an access token from the authorization server's token endpoint by including the authorization code received in the previous step. When making the request, the client authenticates with the authorization server. The client includes the redirection URI used to obtain the authorization code for verification.

curl --compressed -v localhost:8080/v1/oauth/tokens \
	-u test_client_1:test_secret \
	-d "grant_type=authorization_code" \
	-d "code=7afb1c55-76e4-4c76-adb7-9d657cb47a27" \
	-d "redirect_uri=https://www.example.com"

The authorization server authenticates the client, validates the authorization code, and ensures that the redirection URI received matches the URI used to redirect the client before. If valid, the authorization server responds back with an access token and, optionally, a refresh token.

{
  "user_id": "1",
  "access_token": "00ccd40e-72ca-4e79-a4b6-67c95e2e3f1c",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "read_write",
  "refresh_token": "6fd8d272-375a-4d8a-8d0f-43367dc8b791"
}

Implicit

http://tools.ietf.org/html/rfc6749#section-4.2

The implicit grant type is used to obtain access tokens (it does not support the issuance of refresh tokens) and is optimized for public clients known to operate a particular redirection URI. These clients are typically implemented in a browser using a scripting language such as JavaScript.

Since this is a redirection-based flow, the client must be capable of interacting with the resource owner's user-agent (typically a web browser) and capable of receiving incoming requests (via redirection) from the authorization server.

Unlike the authorization code grant type, in which the client makes separate requests for authorization and for an access token, the client receives the access token as the result of the authorization request.

The implicit grant type does not include client authentication, and relies on the presence of the resource owner and the registration of the redirection URI. Because the access token is encoded into the redirection URI, it may be exposed to the resource owner and other applications residing on the same device.

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     ^
     |
    (B)
+----|-----+          Client Identifier     +---------------+
|         -+----(A)-- & Redirection URI --->|               |
|  User-   |                                | Authorization |
|  Agent  -|----(B)-- User authenticates -->|     Server    |
|          |                                |               |
|          |<---(C)--- Redirection URI ----<|               |
|          |          with Access Token     +---------------+
|          |            in Fragment
|          |                                +---------------+
|          |----(D)--- Redirection URI ---->|   Web-Hosted  |
|          |          without Fragment      |     Client    |
|          |                                |    Resource   |
|     (F)  |<---(E)------- Script ---------<|               |
|          |                                +---------------+
+-|--------+
  |    |
 (A)  (G) Access Token
  |    |
  ^    v
+---------+
|         |
|  Client |
|         |
+---------+

The client initiates the flow by directing the resource owner's user-agent to the authorization endpoint. The client includes its client identifier, requested scope, local state, and a redirection URI to which the authorization server will send the user-agent back once access is granted (or denied).

http://localhost:8080/web/authorize?client_id=test_client_1&redirect_uri=https%3A%2F%2Fwww.example.com&response_type=token&state=somestate&scope=read_write

The authorization server authenticates the resource owner (via the user-agent).

Log In page screenshot

The authorization server then establishes whether the resource owner grants or denies the client's access request.

Authorize page screenshot

If the request fails due to a missing, invalid, or mismatching redirection URI, or if the client identifier is missing or invalid, the authorization server SHOULD inform the resource owner of the error and MUST NOT automatically redirect the user-agent to the invalid redirection URI.

If the resource owner denies the access request or if the request fails for reasons other than a missing or invalid redirection URI, the authorization server informs the client by adding the following parameters to the fragment component of the redirection URI.

https://www.example.com/#error=access_denied&state=somestate

Assuming the resource owner grants access, the authorization server redirects the user-agent back to the client using the redirection URI provided earlier. The redirection URI includes he access token in the URI fragment.

https://www.example.com/#access_token=087902d5-29e7-417b-a339-b57a60d6742a&expires_in=3600&scope=read_write&state=somestate&token_type=Bearer

The user-agent follows the redirection instructions by making a request to the web-hosted client resource (which does not include the fragment per [RFC2616]). The user-agent retains the fragment information locally.

The web-hosted client resource returns a web page (typically an HTML document with an embedded script) capable of accessing the full redirection URI including the fragment retained by the user-agent, and extracting the access token (and other parameters) contained in the fragment.

The user-agent executes the script provided by the web-hosted client resource locally, which extracts the access token.

The user-agent passes the access token to the client.

Resource Owner Password Credentials

http://tools.ietf.org/html/rfc6749#section-4.3

The resource owner password credentials grant type is suitable in cases where the resource owner has a trust relationship with the client, such as the device operating system or a highly privileged application. The authorization server should take special care when enabling this grant type and only allow it when other flows are not viable.

This grant type is suitable for clients capable of obtaining the resource owner's credentials (username and password, typically using an interactive form). It is also used to migrate existing clients using direct authentication schemes such as HTTP Basic or Digest authentication to OAuth by converting the stored credentials to an access token.

+----------+
| Resource |
|  Owner   |
|          |
+----------+
     v
     |    Resource Owner
     (A) Password Credentials
     |
     v
+---------+                                  +---------------+
|         |>--(B)---- Resource Owner ------->|               |
|         |         Password Credentials     | Authorization |
| Client  |                                  |     Server    |
|         |<--(C)---- Access Token ---------<|               |
|         |    (w/ Optional Refresh Token)   |               |
+---------+                                  +---------------+

The resource owner provides the client with its username and password.

The client requests an access token from the authorization server's token endpoint by including the credentials received from the resource owner. When making the request, the client authenticates with the authorization server.

curl --compressed -v localhost:8080/v1/oauth/tokens \
	-u test_client_1:test_secret \
	-d "grant_type=password" \
	-d "username=test@user" \
	-d "password=test_password" \
	-d "scope=read_write"

The authorization server authenticates the client and validates the resource owner credentials, and if valid, issues an access token.

{
  "user_id": "1",
  "access_token": "00ccd40e-72ca-4e79-a4b6-67c95e2e3f1c",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "read_write",
  "refresh_token": "6fd8d272-375a-4d8a-8d0f-43367dc8b791"
}

Client Credentials

http://tools.ietf.org/html/rfc6749#section-4.4

The client can request an access token using only its client credentials (or other supported means of authentication) when the client is requesting access to the protected resources under its control, or those of another resource owner that have been previously arranged with the authorization server (the method of which is beyond the scope of this specification).

The client credentials grant type MUST only be used by confidential clients.

+---------+                                  +---------------+
|         |                                  |               |
|         |>--(A)- Client Authentication --->| Authorization |
| Client  |                                  |     Server    |
|         |<--(B)---- Access Token ---------<|               |
|         |                                  |               |
+---------+                                  +---------------+

The client authenticates with the authorization server and requests an access token from the token endpoint.

curl --compressed -v localhost:8080/v1/oauth/tokens \
	-u test_client_1:test_secret \
	-d "grant_type=client_credentials" \
	-d "scope=read_write"

The authorization server authenticates the client, and if valid, issues an access token.

{
  "access_token": "00ccd40e-72ca-4e79-a4b6-67c95e2e3f1c",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "read_write",
  "refresh_token": "6fd8d272-375a-4d8a-8d0f-43367dc8b791"
}

Refreshing An Access Token

http://tools.ietf.org/html/rfc6749#section-6

If the authorization server issued a refresh token to the client, the client can make a refresh request to the token endpoint in order to refresh the access token.

curl --compressed -v localhost:8080/v1/oauth/tokens \
	-u test_client_1:test_secret \
	-d "grant_type=refresh_token" \
	-d "refresh_token=6fd8d272-375a-4d8a-8d0f-43367dc8b791"

The authorization server MUST:

  • require client authentication for confidential clients or for any client that was issued client credentials (or with other authentication requirements),

  • authenticate the client if client authentication is included and ensure that the refresh token was issued to the authenticated client, and

  • validate the refresh token.

If valid and authorized, the authorization server issues an access token.

{
  "user_id": "1",
  "access_token": "1f962bd5-7890-435d-b619-584b6aa32e6c",
  "expires_in": 3600,
  "token_type": "Bearer",
  "scope": "read_write",
  "refresh_token": "3a6b45b8-9d29-4cba-8a1b-0093e8a2b933"
}

The authorization server MAY issue a new refresh token, in which case the client MUST discard the old refresh token and replace it with the new refresh token. The authorization server MAY revoke the old refresh token after issuing a new refresh token to the client. If a new refresh token is issued, the refresh token scope MUST be identical to that of the refresh token included by the client in the request.

Token Introspection

https://tools.ietf.org/html/rfc7662

If the authorization server issued a access token or refresh token to the client, the client can make a request to the introspect endpoint in order to learn meta-information about a token.

curl --compressed -v localhost:8080/v1/oauth/introspect \
	-u test_client_1:test_secret \
	-d "token=00ccd40e-72ca-4e79-a4b6-67c95e2e3f1c" \
	-d "token_type_hint=access_token"

The authorization server responds meta-information about a token.

{
  "active": true,
  "scope": "read_write",
  "client_id": "test_client_1",
  "username": "test@username",
  "token_type": "Bearer",
  "exp": 1454868090
}

Plugins

This server is easily extended or modified through the use of plugins. Four services, health, oauth, session and web are available for modification.

In order to implement a plugin:

  1. Create your own interface that implements all of methods of the service you are replacing.
  2. Modify cmd/run_server.go to use your service by calling the session.Use[service-you-are-replaceing]Service(yourCustomService.NewService()) before the services are initialized via services.Init(cnf, db).

For example, to implement an available redis session storage plugin:

// $ go get https://github.com/adam-hanna/redis-sessions
//
// cmd/run_server.go
import (
    ...
    "github.com/adam-hanna/redis-sessions/redis"
    ...
)

// RunServer runs the app
func RunServer(configBackend string) error {
    ...

    // configure redis for session store
    sessionSecrets := make([][]byte, 1)
    sessionSecrets[0] = []byte(cnf.Session.Secret)
    redisConfig := redis.ConfigType{
        Size:           10,
        Network:        "tcp",
        Address:        ":6379",
        Password:       "",
        SessionSecrets: sessionSecrets,
    }

    // start the services
    services.UseSessionService(redis.NewService(cnf, redisConfig))
    if err := services.InitServices(cnf, db); err != nil {
        return err
    }
    defer services.CloseServices()

    ...
}

Session Storage

By default, this server implements in-memory, cookie sessions via gorilla sessions.

However, because the session service can be replaced via a plugin, any of the available gorilla sessions store implementations can be wrapped by session.ServiceInterface.

Dependencies

Since Go 1.11, a new recommended dependency management system is via modules.

This is one of slight weaknesses of Go as dependency management is not a solved problem. Previously Go was officially recommending to use the dep tool but that has been abandoned now in favor of modules.

Setup

For distributed config storage you can use either etcd or consul (etcd being the default)

If you are developing on OSX, install etcd or consul, Postgres and nats-streaming-server:

etcd

brew install etcd

Load a development configuration into etcd:

ETCDCTL_API=3 etcdctl put /config/go_oauth2_server.json '{
  "Database": {
    "Type": "postgres",
    "Host": "localhost",
    "Port": 5432,
    "User": "go_oauth2_server",
    "Password": "",
    "DatabaseName": "go_oauth2_server",
    "MaxIdleConns": 5,
    "MaxOpenConns": 5
  },
  "Oauth": {
    "AccessTokenLifetime": 3600,
    "RefreshTokenLifetime": 1209600,
    "AuthCodeLifetime": 3600
  },
  "Session": {
    "Secret": "test_secret",
    "Path": "/",
    "MaxAge": 604800,
    "HTTPOnly": true
  },
  "IsDevelopment": true
}'

If you are using etcd API version 3, use etcdctl put instead of etcdctl set.

Check the config was loaded properly:

ETCDCTL_API=3 etcdctl get /config/go_oauth2_server.json

consul

brew install consul

Load a development configuration into consul:

consul kv put /config/go_oauth2_server.json '{
  "Database": {
    "Type": "postgres",
    "Host": "localhost",
    "Port": 5432,
    "User": "go_oauth2_server",
    "Password": "",
    "DatabaseName": "go_oauth2_server",
    "MaxIdleConns": 5,
    "MaxOpenConns": 5
  },
  "Oauth": {
    "AccessTokenLifetime": 3600,
    "RefreshTokenLifetime": 1209600,
    "AuthCodeLifetime": 3600
  },
  "Session": {
    "Secret": "test_secret",
    "Path": "/",
    "MaxAge": 604800,
    "HTTPOnly": true
  },
  "IsDevelopment": true
}'

Check the config was loaded properly:

consul kv get /config/go_oauth2_server.json

Postgres

brew install postgres

You might want to create a Postgres database:

createuser --createdb go_oauth2_server
createdb -U go_oauth2_server go_oauth2_server

Compile & Run

Compile the app:

go install .

The binary accepts an optional flag of --configBackend which can be set to etcd | consul, defaults to etcd

Run migrations:

go-oauth2-server migrate

And finally, run the app:

go-oauth2-server runserver

When deploying, you can set etcd related environment variables:

  • ETCD_ENDPOINTS
  • ETCD_CERT_FILE
  • ETCD_KEY_FILE
  • ETCD_CA_FILE
  • ETCD_CONFIG_PATH

You can also set consul related variables

  • CONSUL_ENDPOINT
  • CONSUL_CERT_FILE
  • CONSUL_KEY_FILE
  • CONSUL_CA_FILE
  • CONSUL_CONFIG_PATH

and the equivalent above commands would be

go-oauth2-server --configBackend consul migrate
go-oauth2-server --configBackend consul runserver

Testing

I have used a mix of unit and functional tests so you need to have sqlite installed in order for the tests to run successfully as the suite creates an in-memory database.

To run tests:

make test

Docker

Build a Docker image and run the app in a container:

docker build -t go-oauth2-server:latest .
docker run -e ETCD_ENDPOINTS=localhost:2379 -p 8080:8080 --name go-oauth2-server go-oauth2-server:latest

You can load fixtures with docker exec command:

docker exec <container_id> /go/bin/go-oauth2-server loaddata \
  oauth/fixtures/scopes.yml \
  oauth/fixtures/roles.yml \
  oauth/fixtures/test_clients.yml

Docker Compose

You can use docker-compose to start the app, postgres, etcd in separate linked containers:

docker-compose up

During docker-compose up process all configuration and fixtures will be loaded. After successful up you can check, that app is running using for example the health check request:

curl --compressed -v localhost:8080/v1/health

Supporting the project

Donate BTC to my wallet if you find this project useful: 12iFVjQ5n3Qdmiai4Mp9EG93NSvDipyRKV

Donate BTC

go-oauth2-server's People

Contributors

adam-hanna avatar ballad89 avatar darkowlzz avatar kfreiman avatar miguelmota avatar richardknop avatar sotosof avatar tebrizetayi avatar yutita avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-oauth2-server's Issues

docker buld does not compile either

docker build -t go-oauth2-server:latest .
Sending build context to Docker daemon 9.801 MB
Step 1/11 : FROM golang
---> ef15416724f6
Step 2/11 : MAINTAINER Richard Knop [email protected]
---> Running in deafd9a40cfd
---> 7bf6019d505e
Removing intermediate container deafd9a40cfd
Step 3/11 : ENV PATH /go/bin:$PATH
---> Running in 08a257c000af
---> fec0353b59bc
Removing intermediate container 08a257c000af
Step 4/11 : RUN useradd --user-group --shell /bin/false app
---> Running in 0b0bd3950e16
---> 1da4125eacda
Removing intermediate container 0b0bd3950e16
Step 5/11 : WORKDIR /go/src/github.com/RichardKnop/go-oauth2-server
---> 2e01ac964f67
Removing intermediate container a4f9b13faf71
Step 6/11 : ADD . /go/src/github.com/RichardKnop/go-oauth2-server
---> 8431492bbf64
Removing intermediate container 4d02fafae8fd
Step 7/11 : RUN chown -R app:app /go/src/github.com/RichardKnop/go-oauth2-server/
---> Running in fb9437b3f4ce
---> b289fbe03a91
Removing intermediate container fb9437b3f4ce
Step 8/11 : USER app
---> Running in 7616f58ec03e
---> f55c6eb1f370
Removing intermediate container 7616f58ec03e
Step 9/11 : RUN go install github.com/RichardKnop/go-oauth2-server
---> Running in ebb11a37a17e
cmd/load_data.go:4:2: cannot find package "github.com/RichardKnop/go-fixtures" in any of:
/usr/local/go/src/github.com/RichardKnop/go-fixtures (from $GOROOT)
/go/src/github.com/RichardKnop/go-fixtures (from $GOPATH)
util/response/list.go:4:2: cannot find package "github.com/RichardKnop/jsonhal" in any of:
/usr/local/go/src/github.com/RichardKnop/jsonhal (from $GOROOT)
/go/src/github.com/RichardKnop/jsonhal (from $GOPATH)
logger/logger.go:4:2: cannot find package "github.com/RichardKnop/logging" in any of:
/usr/local/go/src/github.com/RichardKnop/logging (from $GOROOT)
/go/src/github.com/RichardKnop/logging (from $GOPATH)
models/oauth.go:8:2: cannot find package "github.com/RichardKnop/uuid" in any of:
/usr/local/go/src/github.com/RichardKnop/uuid (from $GOROOT)
/go/src/github.com/RichardKnop/uuid (from $GOPATH)
config/etcd.go:10:2: cannot find package "github.com/coreos/etcd/clientv3" in any of:
/usr/local/go/src/github.com/coreos/etcd/clientv3 (from $GOROOT)
/go/src/github.com/coreos/etcd/clientv3 (from $GOPATH)
config/etcd.go:11:2: cannot find package "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" in any of:
/usr/local/go/src/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes (from $GOROOT)
/go/src/github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes (from $GOPATH)
config/etcd.go:12:2: cannot find package "github.com/coreos/etcd/pkg/transport" in any of:
/usr/local/go/src/github.com/coreos/etcd/pkg/transport (from $GOROOT)
/go/src/github.com/coreos/etcd/pkg/transport (from $GOPATH)
web/context.go:9:2: cannot find package "github.com/gorilla/context" in any of:
/usr/local/go/src/github.com/gorilla/context (from $GOROOT)
/go/src/github.com/gorilla/context (from $GOPATH)
util/routes/routes.go:6:2: cannot find package "github.com/gorilla/mux" in any of:
/usr/local/go/src/github.com/gorilla/mux (from $GOROOT)
/go/src/github.com/gorilla/mux (from $GOPATH)
session/service.go:9:2: cannot find package "github.com/gorilla/sessions" in any of:
/usr/local/go/src/github.com/gorilla/sessions (from $GOROOT)
/go/src/github.com/gorilla/sessions (from $GOPATH)
config/consul.go:10:2: cannot find package "github.com/hashicorp/consul/api" in any of:
/usr/local/go/src/github.com/hashicorp/consul/api (from $GOROOT)
/go/src/github.com/hashicorp/consul/api (from $GOPATH)
database/database.go:7:2: cannot find package "github.com/jinzhu/gorm" in any of:
/usr/local/go/src/github.com/jinzhu/gorm (from $GOROOT)
/go/src/github.com/jinzhu/gorm (from $GOPATH)
database/database.go:10:2: cannot find package "github.com/lib/pq" in any of:
/usr/local/go/src/github.com/lib/pq (from $GOROOT)
/go/src/github.com/lib/pq (from $GOPATH)
web/render.go:9:2: cannot find package "github.com/oxtoacart/bpool" in any of:
/usr/local/go/src/github.com/oxtoacart/bpool (from $GOROOT)
/go/src/github.com/oxtoacart/bpool (from $GOPATH)
cmd/run_server.go:9:2: cannot find package "github.com/phyber/negroni-gzip/gzip" in any of:
/usr/local/go/src/github.com/phyber/negroni-gzip/gzip (from $GOROOT)
/go/src/github.com/phyber/negroni-gzip/gzip (from $GOPATH)
util/secure.go:4:2: cannot find package "github.com/unrolled/secure" in any of:
/usr/local/go/src/github.com/unrolled/secure (from $GOROOT)
/go/src/github.com/unrolled/secure (from $GOPATH)
go_oauth2_server.go:8:2: cannot find package "github.com/urfave/cli" in any of:
/usr/local/go/src/github.com/urfave/cli (from $GOROOT)
/go/src/github.com/urfave/cli (from $GOPATH)
util/response/logging.go:11:2: cannot find package "github.com/urfave/negroni" in any of:
/usr/local/go/src/github.com/urfave/negroni (from $GOROOT)
/go/src/github.com/urfave/negroni (from $GOPATH)
util/password/password.go:4:2: cannot find package "golang.org/x/crypto/bcrypt" in any of:
/usr/local/go/src/golang.org/x/crypto/bcrypt (from $GOROOT)
/go/src/golang.org/x/crypto/bcrypt (from $GOPATH)
config/etcd.go:13:2: cannot find package "golang.org/x/net/context" in any of:
/usr/local/go/src/golang.org/x/net/context (from $GOROOT)
/go/src/golang.org/x/net/context (from $GOPATH)
cmd/run_server.go:11:2: cannot find package "gopkg.in/tylerb/graceful.v1" in any of:
/usr/local/go/src/gopkg.in/tylerb/graceful.v1 (from $GOROOT)
/go/src/gopkg.in/tylerb/graceful.v1 (from $GOPATH)
The command '/bin/sh -c go install github.com/RichardKnop/go-oauth2-server' returned a non-zero code: 1

Problem with the configuration reloading

There is an option (keepReloading) in the config/factory.go which is not working. If it is enabled it is create a go routine which reload the configuration, but this function called only once for me. So if I change the configuration and the application don't know its happened. You should create a channel for that which is listening for configuration changes and add this as a parameter for the NewConfig function.

Anyway, thank you for the nice tool.

Implicit grant not checking the Redirect URL

In OAuth2 for the implicit grant you have to check the Redirect URL, because in this case this is the only way to authorize the client identify. I checked and your application not check it, and I can use any redirect URL if I know the client key.
If you agree it, I can create a pull request for fill the security hole.

docker compose up error

I can't run docker-compose up since it's returning this error

Step 12/14 : RUN go install github.com/RichardKnop/go-oauth2-server
 ---> Running in 61490ad04ee6
go: downloading github.com/urfave/cli v0.0.0-20180106191048-75104e932ac2
go: downloading github.com/jinzhu/gorm v1.9.2
go: downloading gopkg.in/tylerb/graceful.v1 v1.2.15
go: downloading github.com/RichardKnop/go-fixtures v0.0.0-20181101035649-15577dcaa372
go: downloading github.com/gorilla/mux v1.7.0
go: downloading github.com/phyber/negroni-gzip v0.0.0-20180113114010-ef6356a5d029
go: downloading github.com/RichardKnop/uuid v0.0.0-20160216163710-c55201b03606
go: downloading github.com/gorilla/context v1.1.1
go: downloading github.com/coreos/etcd v3.3.12+incompatible
go: extracting gopkg.in/tylerb/graceful.v1 v1.2.15
go: extracting github.com/RichardKnop/uuid v0.0.0-20160216163710-c55201b03606
go: extracting github.com/gorilla/context v1.1.1
go: downloading github.com/RichardKnop/logging v0.0.0-20181101035820-b1d5d44c82d6
go: extracting github.com/gorilla/mux v1.7.0
go: extracting github.com/phyber/negroni-gzip v0.0.0-20180113114010-ef6356a5d029
go: downloading github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2
go: extracting github.com/jinzhu/gorm v1.9.2
go: downloading golang.org/x/net v0.0.0-20190213061140-3a22650c66bd
go: extracting github.com/RichardKnop/go-fixtures v0.0.0-20181101035649-15577dcaa372
go: extracting github.com/urfave/cli v0.0.0-20180106191048-75104e932ac2
go: downloading github.com/lib/pq v1.0.0
go: downloading github.com/hashicorp/consul v1.4.2
go: downloading golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2
go: extracting github.com/RichardKnop/logging v0.0.0-20181101035820-b1d5d44c82d6
go: downloading github.com/unrolled/secure v1.0.0
go: extracting github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2
go: downloading github.com/urfave/negroni v1.0.0
go: downloading github.com/jinzhu/inflection v0.0.0-20180308033659-04140366298a
go: extracting github.com/lib/pq v1.0.0
go: downloading github.com/gorilla/sessions v1.1.3
go: extracting golang.org/x/net v0.0.0-20190213061140-3a22650c66bd
verifying github.com/coreos/[email protected]+incompatible: checksum mismatch
        downloaded: h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ=
        go.sum:     h1:5k8nkcBSvltjOO5RLflnXevOJXndlKIMbvVnMTX+cUU=

SECURITY ERROR
This download does NOT match an earlier download recorded in go.sum.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.

For more information, see 'go help module-auth'.

please help. thanks

dependent package errors

make update-deps:
godep: Package (golang.org/x/net/context) not found

make install-deps:
unrecognized import path "golang.org/x/crypto/bcrypt
unrecognized import path "golang.org/x/crypto/blowfish"
unrecognized import path "golang.org/x/net/context"

and how to solved it ?

how to generate client?

I don't find any route or command to oauth2 client , where is it please? I also read all document , still not find any reference. I check all source codes, it seems we need to add a command to generate client ourself, this feature is quite common, why it is not implemented internally?

Docker container not starting

Commands:

  1. git clone https://github.com/RichardKnop/go-oauth2-server.git

  2. cd go-oauth2-server/

  3. docker build -t go-oauth2-server:latest .

  4. docker run -e ETCD_ENDPOINTS=localhost:2379 -p 8070:8080 --name go-oauth2-server go-oauth2-server:latest

Result:

Postgres is up - executing command:
NAME:
   go-oauth2-server - Go OAuth 2.0 Server

USAGE:
   go-oauth2-server [global options] command [command options] [arguments...]

VERSION:
   0.0.0

AUTHOR:
   Richard Knop <[email protected]>

COMMANDS:
     migrate    run migrations
     loaddata   load data from fixture
     runserver  run web server
     help, h    Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --configBackend value  (default: "etcd")
   --help, -h             show help
   --version, -v          print the version

But the container is not running:

docker exec go-oauth2-server /go/bin/go-oauth2-server loaddata \
>   oauth/fixtures/scopes.yml \
>   oauth/fixtures/roles.yml \
>   oauth/fixtures/test_clients.yml

Error response from daemon: Container 1a61b8dfdc65cf13f91edd5d7f2ab954215e38f20e8cda629c94ed8adf034930 is not running

What I have done wrong ?

bare bones set of commands and endpoints for admin and testing purposes

Thanks for putting this great project together. I've built the go-oauth2-server and it seems to run fine but I'm having trouble figuring out how to actually use it. Apologies in advance if these questions are covered in documentation somewhere that I missed, but how can I do the following basic tasks for testing purposes? If it's just a series of generic SQL INSERT statements, that's fine:

  1. add users (providing the userid and password). How do I do this? Do I have to create both a role, as well as a user, to populate the oauth_roles and oauth_users tables? Are there predefined roles? Can I populate the related database tables directly with a SQL statement or should that be done through a command or endpoint request?
  2. Will I need to add a scope and associate that scope with something in the response data (are there predefined scopes?) in order to make a successful client authentication call?
  3. How do I register an application (by providing a redirect_uri) and receive back (and/or provide) the related client_id and client_secret?

Past the above 3 server-side steps, it would be ideal to have a sample client test script (in any language), such as the sample python client script for Google OAuth. To do this, I think the only additional info needed would be the endpoints for:
authorization_base_url e.g. "https://localhost:8080/o/oauth2/v2/auth"
token_url e.g. "https://localhost:8080/oauth2/v4/token"
refresh_url e.g. "https://localhost:8080/oauth2/v4/token"
scope(s): e.g. "https://localhost:8080/auth/userinfo.email"

Any suggestions or guidance would be much appreciated!

I don't see how roles are used

I see roles in DB schema, but I don't seem to find how it is used.

Bit more digging shows that there are built-in user and superuser roles. It seems that roles are internal to the application services. Am I correct?

Thank you

Docker compose fails to start

When running the docker-compose docker-compose up I get this error.

etcd-config_1       | OK
go-oauth2-server    | INFO: 2016/12/10 12:34:55 factory.go:155 ETCD Endpoints: http://etcd:2379
go-oauth2-server    | FATAL: 2016/12/10 12:34:55 factory.go:92 100: Key not found (/config) [3]
etcd_1              | 2016-12-10 11:18:52.097867 W | flags: unrecognized environment variable ETCDCTL_API=3
etcd_1              | 2016-12-10 11:18:52.097963 I | etcdmain: etcd Version: 3.0.15
etcd_1              | 2016-12-10 11:18:52.097970 I | etcdmain: Git SHA: fc00305
etcd_1              | 2016-12-10 11:18:52.097975 I | etcdmain: Go Version: go1.6.3
etcd_1              | 2016-12-10 11:18:52.097981 I | etcdmain: Go OS/Arch: linux/amd64
etcd_1              | 2016-12-10 11:18:52.097987 I | etcdmain: setting maximum number of CPUs to 4, total number of available CPUs is 4
etcd_1              | 2016-12-10 11:18:52.097993 W | etcdmain: no data-dir provided, using default data-dir ./default.etcd
etcd_1              | 2016-12-10 11:18:52.103629 I | etcdmain: listening for peers on http://localhost:2380
etcd_1              | 2016-12-10 11:18:52.103718 I | etcdmain: listening for client requests on 0.0.0.0:2379
etcd_1              | 2016-12-10 11:18:52.115918 I | etcdserver: name = default
etcd_1              | 2016-12-10 11:18:52.115948 I | etcdserver: data dir = default.etcd
etcd_1              | 2016-12-10 11:18:52.115956 I | etcdserver: member dir = default.etcd/member
etcd_1              | 2016-12-10 11:18:52.115962 I | etcdserver: heartbeat = 100ms
etcd_1              | 2016-12-10 11:18:52.115967 I | etcdserver: election = 1000ms
gooauth2server_etcd-config_1 exited with code 0
etcd_1              | 2016-12-10 11:18:52.116103 I | etcdserver: snapshot count = 10000
etcd_1              | 2016-12-10 11:18:52.116131 I | etcdserver: advertise client URLs = http://127.0.0.1:2379
etcd_1              | 2016-12-10 11:18:52.116139 I | etcdserver: initial advertise peer URLs = http://localhost:2380
etcd_1              | 2016-12-10 11:18:52.116207 I | etcdserver: initial cluster = default=http://localhost:2380
etcd_1              | 2016-12-10 11:18:52.165290 I | etcdserver: starting member 8e9e05c52164694d in cluster cdf818194e3a8c32
etcd_1              | 2016-12-10 11:18:52.165370 I | raft: 8e9e05c52164694d became follower at term 0
etcd_1              | 2016-12-10 11:18:52.165390 I | raft: newRaft 8e9e05c52164694d [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]
etcd_1              | 2016-12-10 11:18:52.165400 I | raft: 8e9e05c52164694d became follower at term 1
etcd_1              | 2016-12-10 11:18:52.224602 I | etcdserver: starting server... [version: 3.0.15, cluster version: to_be_decided]
etcd_1              | 2016-12-10 11:18:52.225592 I | membership: added member 8e9e05c52164694d [http://localhost:2380] to cluster cdf818194e3a8c32
etcd_1              | 2016-12-10 11:18:52.417490 I | raft: 8e9e05c52164694d is starting a new election at term 1
etcd_1              | 2016-12-10 11:18:52.417595 I | raft: 8e9e05c52164694d became candidate at term 2
etcd_1              | 2016-12-10 11:18:52.417631 I | raft: 8e9e05c52164694d received vote from 8e9e05c52164694d at term 2
etcd_1              | 2016-12-10 11:18:52.417808 I | raft: 8e9e05c52164694d became leader at term 2
etcd_1              | 2016-12-10 11:18:52.417867 I | raft: raft.node: 8e9e05c52164694d elected leader 8e9e05c52164694d at term 2
etcd_1              | 2016-12-10 11:18:52.418712 I | etcdserver: setting up the initial cluster version to 3.0
etcd_1              | 2016-12-10 11:18:52.419736 N | membership: set the initial cluster version to 3.0
etcd_1              | 2016-12-10 11:18:52.419845 I | api: enabled capabilities for version 3.0
etcd_1              | 2016-12-10 11:18:52.419981 I | etcdserver: published {Name:default ClientURLs:[http://127.0.0.1:2379]} to cluster cdf818194e3a8c32
etcd_1              | 2016-12-10 11:18:52.420041 I | etcdmain: ready to serve client requests
etcd_1              | 2016-12-10 11:18:52.420765 N | etcdmain: serving insecure client requests on 0.0.0.0:2379, this is strongly discouraged!
postgres_1          | LOG:  database system was shut down at 2016-10-29 15:24:04 UTC
postgres_1          | LOG:  MultiXact member wraparound protections are now enabled
postgres_1          | LOG:  database system is ready to accept connections
postgres_1          | LOG:  autovacuum launcher started
go-oauth2-server exited with code 1

is jwt ready now?

I'd like to pass jwt token to my micro services, can we use jwt now out of box now?

FATAL: 2016/12/03 16:47:02 factory.go:84 key not found: /config/go_oauth2_server.json

I install etdc and set the go_oauth2_server.json. after set the config,i use

etcdctl get  /config/go_oauth2_server.json

i see my config is success

and after i install pg,i run ./go-oauth2-server migrate
but i got this message

INFO: 2016/12/03 16:41:29 factory.go:169 ETCD Endpoints: http://127.0.0.1:2379
FATAL: 2016/12/03 16:41:29 factory.go:84 key not found: /config/go_oauth2_server.json

i do not know why ,i think my config is right

database scope check fails

Hi, I've been some days trying to use the server and I'm having a problem that is bothering me and I can't understand where it comes from.

I've used consul and postgres to setup the server. When I'm login in, the client and user checks go well, but it doesn't find the scopes I created in my database.->

[2.68ms] SELECT count(*) FROM "oauth_scopes" WHERE "oauth_scopes"."deleted_at" IS NULL AND ((scope=('read'))) [0 rows affected or returned ]

The same goes with the "is_default" check. If I try to search it using exactly the same code in my database, the rows actually appear with no problem.->

`go_oauth2_server=# SELECT count(*) FROM "oauth_scopes" WHERE "oauth_scopes"."deleted_at" IS NULL AND ((scope=('read'))) ;
count

 1

(1 row)`

Thanks in advance for the help.

build errror

go: disabling cache (/home/app/.cache/go-build) due to initialization failure: mkdir /home/app: permission denied
I am deploying on an Azure Docker Swarm Linux Container

SQL syntax error on introspect

On trying to do an introspect on an access_token, I'm seeing the following error in the log:

[2017-10-08 09:56:55]  [1.20ms]  SELECT * FROM "oauth_access_tokens"  WHERE "oauth_access_tokens"."deleted_at" IS NULL AND ((token = '925c405b-b593-48c9-bc4e-48962d3e0401')) ORDER BY "oauth_access_tokens"."id" ASC LIMIT 1

(/go/src/github.com/RichardKnop/go-oauth2-server/oauth/authenticate.go:45) 
[2017-10-08 09:56:55]  [0.60ms]  UPDATE "oauth_refresh_tokens" SET "expires_at" = '2017-10-22 09:56:55'  WHERE "oauth_refresh_tokens"."deleted_at" IS NULL AND ((client_id = '1') AND (user_id = 'bdeb6242-e6b1-4799-bfee-3b0e7458083a'))

(/go/src/github.com/RichardKnop/go-oauth2-server/oauth/introspect.go:74) 
[2017-10-08 09:56:55]  [0.55ms]  SELECT key FROM "oauth_clients"  WHERE "oauth_clients"."deleted_at" IS NULL AND (("oauth_clients"."id" = '1')) ORDER BY "oauth_clients"."id" ASC LIMIT 1

(/go/src/github.com/RichardKnop/go-oauth2-server/oauth/introspect.go:84) 
[2017-10-08 09:56:55]  pq: syntax error at or near "b0e7458083a" 

(/go/src/github.com/RichardKnop/go-oauth2-server/oauth/introspect.go:84) 
[2017-10-08 09:56:55]  [0.47ms]  SELECT username FROM "oauth_users"  WHERE "oauth_users"."deleted_at" IS NULL AND ((bdeb6242-e6b1-4799-bfee-3b0e7458083a)) ORDER BY "oauth_users"."id" ASC LIMIT 1
[negroni] 2017-10-08T09:56:55Z | 200 |   104.117984ms | go_oauth2_server:8080 | POST /v1/oauth/introspect 

So, everything but the username I am actually interested in is returned to the OAuth client. I use the docker container, but maybe I'm still just getting something wrong.

By the way, in the documentation on line 126, it says that in the authorization_code grant response with the access_token, the server also returns a user_id (that may be persistent also after requesting a new access_token?). However, I'm never actually seeing this user_id being returned.

Thanks a lot for your efforts.

Docker-compose issue: not starting after cloning the repo

INFO: 2016/09/20 07:40:55 factory.go:154 ETCD Endpoint: http://etcd:2379
INFO: 2016/09/20 07:40:55 factory.go:100 Successfully loaded config for the first time
INFO: 2016/09/20 07:40:55 factory.go:154 ETCD Endpoint: http://etcd:2379
INFO: 2016/09/20 07:40:55 factory.go:100 Successfully loaded config for the first time
INFO: 2016/09/20 07:40:55 factory.go:154 ETCD Endpoint: http://etcd:2379
INFO: 2016/09/20 07:40:55 factory.go:100 Successfully loaded config for the first time
Error loading file accounts/fixtures/roles.yml: open accounts/fixtures/roles.yml: no such file or directory

This happens when I git clone the repo and write docker-compose up

Docker version: 1.12.1
Docker-compose: 1.8.0

UUID rather than sequential integers for id's (possible pull request)

Sorry to be spamming the issues board today...

I thought I'd take a stab at modifying the codebase to use uuid's rather than sequential ints for ids. Let me know your thoughts on the below. It passes all tests and should be sql engine agnostic as the uuid's are generated in go code rather than in the db.
https://github.com/adam-hanna/go-oauth2-server/tree/feature/uuid

It's a few commits behind this repo and needs some linting / general cleanup but it's mostly there. Let me know your thoughts and I will get it up to current, clean it up and get it ready for a pull request.

Thanks!

Error from docker during build

I get the error below when trying to build using docker compose. Any idea how to fix?

verifying github.com/coreos/[email protected]+incompatible: checksum mismatch
downloaded: h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ=
go.sum: h1:5k8nkcBSvltjOO5RLflnXevOJXndlKIMbvVnMTX+cUU=
Service 'app' failed to build: The command '/bin/sh -c go install github.com/RichardKnop/go-oauth2-server' returned a non-zero code: 1
Failed to deploy 'Compose: docker-compose.yml': docker-compose process finished with exit code 1

struggling to get database initialized properly

Hi,
Despite having the same issue with docker-compose as in #21, after restarting it multiple times it seems to bring up everything. However, the database is not populated with the user accounts nor the test clients. I tried to enter the information by hand, but it's quite a mess. With docker-compose, shouldn't it enter all the information automatically?
Best
Clemens

Dependencies

Why does this depend on so many heavy weight things? Etcd, Postgres? Can we lighten the dependencies at all?

User data

When inserting user data.Is there a utility to help with that?(some package,with some method). How do we hash the passwords.bcrypt,md5?

connection refused / cannot start go-oauth2-server

Am running OSX and was able to build and install without any problem. Then I tried to run, but it fails after about 5 seconds with the FATAL message shown below:

go-oauth2-server runserver
INFO: 2018/01/19 17:44:02 etcd.go:90 ETCD Endpoints: http://localhost:2379
FATAL: 2018/01/19 17:44:07 factory.go:71 dial tcp [::1]:2379: getsockopt: connection refused

This looks like a similar issue to the closed issue #15. Any suggestions?

Problem migrate from PostgreSQL to MySQL

When I was trying to migrate from PostgreSQL to MySQL, it took more effort than I thought. Due to the inconsistent data type of IDs, when gorm try to create foreign key, following error occurs:

Error 1215: Cannot add foreign key constraint

gorm defines the ID with unit type, which maps to MySQL int(10) unsigned:

package gorm

import "time"

type Model struct {
    ID        uint `gorm:"primary_key"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt *time.Time `sql:"index"`
}

But ClientID, UserID defined as sql.NullInt64, which map to MySQL bigint(20):

type RefreshToken struct {
    gorm.Model
    ClientID  sql.NullInt64 `sql:"index;not null"`
    UserID    sql.NullInt64 `sql:"index"`
    Client    *Client
    User      *User
    Token     string    `sql:"type:varchar(40);unique;not null"`
    ExpiresAt time.Time `sql:"not null"`
    Scope     string    `sql:"type:varchar(200);not null"`
}

Docker compose: Database is uninitialized and superuser password is not specified.

When you want to run it using docker-compose , it gives error

Error: Database is uninitialized and superuser password is not specified.
You must specify POSTGRES_PASSWORD to a non-empty value for the
superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
connections without a password. This is not recommended.

See PostgreSQL documentation about "trust":
https://www.postgresql.org/docs/current/auth-trust.html

how to run this project

i recieve this errro when type go install .
:go-oauth2-server.go:7:2: cannot find package "github.com/RichardKnop/go-oauth2-server/cmd" in any of:

go-oauth2-server exits immediately

After I run docker-compose up I get:

bash-3.2$ docker-compose up
gooauth2server_postgres_1 is up-to-date
gooauth2server_etcd_1 is up-to-date
Creating go-oauth2-server
Attaching to gooauth2server_postgres_1, gooauth2server_etcd_1, go-oauth2-server
go-oauth2-server    | INFO: 2016/09/30 11:06:33 factory.go:155 ETCD Endpoints: http://localhost:2379
go-oauth2-server    | FATAL: 2016/09/30 11:06:33 factory.go:92 client: etcd cluster is unavailable or misconfigured; error #0: dial tcp [::1]:2379: getsockopt: connection refused
go-oauth2-server    |
etcd_1              | Using default CLIENT_URLS (http://0.0.0.0:4001,http://0.0.0.0:2379)
etcd_1              | Using default PEER_URLS (http://0.0.0.0:7001,http://0.0.0.0:2380)
etcd_1              | Running '/bin/etcd -data-dir=/data -listen-peer-urls=http://0.0.0.0:7001,http://0.0.0.0:2380 -listen-client-urls=http://0.0.0.0:4001,http://0.0.0.0:2379 '
etcd_1              | BEGIN ETCD OUTPUT
etcd_1              |
etcd_1              | 2016/09/30 10:35:52 etcd: listening for peers on http://0.0.0.0:2380
etcd_1              | 2016/09/30 10:35:52 etcd: listening for peers on http://0.0.0.0:7001
etcd_1              | 2016/09/30 10:35:52 etcd: listening for client requests on http://0.0.0.0:2379
etcd_1              | 2016/09/30 10:35:52 etcd: listening for client requests on http://0.0.0.0:4001
etcd_1              | 2016/09/30 10:35:52 etcdserver: datadir is valid for the 2.0.1 format
etcd_1              | 2016/09/30 10:35:52 etcdserver: name = default
etcd_1              | 2016/09/30 10:35:52 etcdserver: data dir = /data
etcd_1              | 2016/09/30 10:35:52 etcdserver: member dir = /data/member
etcd_1              | 2016/09/30 10:35:52 etcdserver: heartbeat = 100ms
etcd_1              | 2016/09/30 10:35:52 etcdserver: election = 1000ms
etcd_1              | 2016/09/30 10:35:52 etcdserver: snapshot count = 10000
etcd_1              | 2016/09/30 10:35:52 etcdserver: advertise client URLs = http://localhost:2379,http://localhost:4001
etcd_1              | 2016/09/30 10:35:52 etcdserver: initial advertise peer URLs = http://localhost:2380,http://localhost:7001
etcd_1              | 2016/09/30 10:35:52 etcdserver: initial cluster = default=http://localhost:2380,default=http://localhost:7001
etcd_1              | 2016/09/30 10:35:52 etcdserver: start member ce2a822cea30bfca in cluster 7e27652122e8b2ae
etcd_1              | 2016/09/30 10:35:52 raft: ce2a822cea30bfca became follower at term 0
etcd_1              | 2016/09/30 10:35:52 raft: newRaft ce2a822cea30bfca [peers: [], term: 0, commit: 0, applied: 0, lastindex: 0, lastterm: 0]
etcd_1              | 2016/09/30 10:35:52 raft: ce2a822cea30bfca became follower at term 1
etcd_1              | 2016/09/30 10:35:52 etcdserver: added local member ce2a822cea30bfca [http://localhost:2380 http://localhost:7001] to cluster 7e27652122e8b2ae
etcd_1              | 2016/09/30 10:35:54 raft: ce2a822cea30bfca is starting a new election at term 1
etcd_1              | 2016/09/30 10:35:54 raft: ce2a822cea30bfca became candidate at term 2
etcd_1              | 2016/09/30 10:35:54 raft: ce2a822cea30bfca received vote from ce2a822cea30bfca at term 2
etcd_1              | 2016/09/30 10:35:54 raft: ce2a822cea30bfca became leader at term 2
etcd_1              | 2016/09/30 10:35:54 raft.node: ce2a822cea30bfca elected leader ce2a822cea30bfca at term 2
etcd_1              | 2016/09/30 10:35:54 etcdserver: published {Name:default ClientURLs:[http://localhost:2379 http://localhost:4001]} to cluster 7e27652122e8b2ae
etcd_1              | Using default CLIENT_URLS (http://0.0.0.0:4001,http://0.0.0.0:2379)
postgres_1          | The files belonging to this database system will be owned by user "postgres".
etcd_1              | Using default PEER_URLS (http://0.0.0.0:7001,http://0.0.0.0:2380)
postgres_1          | This user must also own the server process.
etcd_1              | Running '/bin/etcd -data-dir=/data -listen-peer-urls=http://0.0.0.0:7001,http://0.0.0.0:2380 -listen-client-urls=http://0.0.0.0:4001,http://0.0.0.0:2379 '
postgres_1          |
etcd_1              | BEGIN ETCD OUTPUT
postgres_1          | The database cluster will be initialized with locale "en_US.utf8".
etcd_1              |
etcd_1              | 2016/09/30 10:56:10 etcd: already initialized as member before, starting as etcd member...
postgres_1          | The default database encoding has accordingly been set to "UTF8".
etcd_1              | 2016/09/30 10:56:10 etcd: listening for peers on http://0.0.0.0:2380
postgres_1          | The default text search configuration will be set to "english".
postgres_1          |
etcd_1              | 2016/09/30 10:56:10 etcd: listening for peers on http://0.0.0.0:7001
postgres_1          | Data page checksums are disabled.
etcd_1              | 2016/09/30 10:56:10 etcd: listening for client requests on http://0.0.0.0:2379
etcd_1              | 2016/09/30 10:56:10 etcd: listening for client requests on http://0.0.0.0:4001
postgres_1          |
etcd_1              | 2016/09/30 10:56:10 etcdserver: datadir is valid for the 2.0.1 format
postgres_1          | fixing permissions on existing directory /var/lib/postgresql/data ... ok
etcd_1              | 2016/09/30 10:56:10 etcdserver: name = default
etcd_1              | 2016/09/30 10:56:10 etcdserver: data dir = /data
etcd_1              | 2016/09/30 10:56:10 etcdserver: member dir = /data/member
postgres_1          | creating subdirectories ... ok
postgres_1          | selecting default max_connections ... 100
postgres_1          | selecting default shared_buffers ... 128MB
postgres_1          | selecting dynamic shared memory implementation ... posix
postgres_1          | creating configuration files ... ok
etcd_1              | 2016/09/30 10:56:10 etcdserver: heartbeat = 100ms
etcd_1              | 2016/09/30 10:56:10 etcdserver: election = 1000ms
postgres_1          | creating template1 database in /var/lib/postgresql/data/base/1 ... ok
postgres_1          | initializing pg_authid ... ok
postgres_1          | initializing dependencies ... ok
etcd_1              | 2016/09/30 10:56:10 etcdserver: snapshot count = 10000
postgres_1          | creating system views ... ok
etcd_1              | 2016/09/30 10:56:10 etcdserver: advertise client URLs = http://localhost:2379,http://localhost:4001
etcd_1              | 2016/09/30 10:56:10 etcdserver: restart member ce2a822cea30bfca in cluster 7e27652122e8b2ae at commit index 2412
postgres_1          | loading system objects' descriptions ... ok
etcd_1              | 2016/09/30 10:56:10 raft: ce2a822cea30bfca became follower at term 2
postgres_1          | creating collations ... ok
etcd_1              | 2016/09/30 10:56:10 raft: newRaft ce2a822cea30bfca [peers: [], term: 2, commit: 2412, applied: 0, lastindex: 2412, lastterm: 2]
etcd_1              | 2016/09/30 10:56:10 etcdserver: added local member ce2a822cea30bfca [http://localhost:2380 http://localhost:7001] to cluster 7e27652122e8b2ae
postgres_1          | creating conversions ... ok
etcd_1              | 2016/09/30 10:56:11 raft: ce2a822cea30bfca is starting a new election at term 2
postgres_1          | creating dictionaries ... ok
etcd_1              | 2016/09/30 10:56:11 raft: ce2a822cea30bfca became candidate at term 3
etcd_1              | 2016/09/30 10:56:11 raft: ce2a822cea30bfca received vote from ce2a822cea30bfca at term 3
postgres_1          | setting privileges on built-in objects ... ok
etcd_1              | 2016/09/30 10:56:11 raft: ce2a822cea30bfca became leader at term 3
postgres_1          | creating information schema ... ok
etcd_1              | 2016/09/30 10:56:11 raft.node: ce2a822cea30bfca elected leader ce2a822cea30bfca at term 3
postgres_1          | loading PL/pgSQL server-side language ... ok
etcd_1              | 2016/09/30 10:56:11 etcdserver: published {Name:default ClientURLs:[http://localhost:2379 http://localhost:4001]} to cluster 7e27652122e8b2ae
postgres_1          | vacuuming database template1 ... ok
postgres_1          | copying template1 to template0 ... ok
postgres_1          | copying template1 to postgres ... ok
postgres_1          | syncing data to disk ... ok
postgres_1          |
postgres_1          | WARNING: enabling "trust" authentication for local connections
postgres_1          | You can change this by editing pg_hba.conf or using the option -A, or
postgres_1          | --auth-local and --auth-host, the next time you run initdb.
postgres_1          |
postgres_1          | Success. You can now start the database server using:
postgres_1          |
postgres_1          |     pg_ctl -D /var/lib/postgresql/data -l logfile start
postgres_1          |
postgres_1          | ****************************************************
postgres_1          | WARNING: No password has been set for the database.
postgres_1          |          This will allow anyone with access to the
postgres_1          |          Postgres port to access your database. In
postgres_1          |          Docker's default configuration, this is
postgres_1          |          effectively any other container on the same
postgres_1          |          system.
postgres_1          |
postgres_1          |          Use "-e POSTGRES_PASSWORD=password" to set
postgres_1          |          it in "docker run".
postgres_1          | ****************************************************
postgres_1          | waiting for server to start....LOG:  database system was shut down at 2016-09-30 10:35:53 UTC
postgres_1          | LOG:  MultiXact member wraparound protections are now enabled
postgres_1          | LOG:  database system is ready to accept connections
postgres_1          | LOG:  autovacuum launcher started
postgres_1          |  done
postgres_1          | server started
postgres_1          | CREATE DATABASE
postgres_1          |
postgres_1          | CREATE ROLE
postgres_1          |
postgres_1          |
postgres_1          | /docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
postgres_1          |
postgres_1          | LOG:  received fast shutdown request
postgres_1          | LOG:  aborting any active transactions
postgres_1          | LOG:  autovacuum launcher shutting down
postgres_1          | LOG:  shutting down
postgres_1          | waiting for server to shut down....LOG:  database system is shut down
postgres_1          |  done
postgres_1          | server stopped
postgres_1          |
postgres_1          | PostgreSQL init process complete; ready for start up.
postgres_1          |
postgres_1          | LOG:  database system was shut down at 2016-09-30 10:35:55 UTC
postgres_1          | LOG:  MultiXact member wraparound protections are now enabled
postgres_1          | LOG:  database system is ready to accept connections
postgres_1          | LOG:  autovacuum launcher started
postgres_1          | LOG:  database system was interrupted; last known up at 2016-09-30 10:35:56 UTC
postgres_1          | LOG:  database system was not properly shut down; automatic recovery in progress
postgres_1          | LOG:  invalid record length at 0/1708128
postgres_1          | LOG:  redo is not required
postgres_1          | LOG:  MultiXact member wraparound protections are now enabled
postgres_1          | LOG:  database system is ready to accept connections
postgres_1          | LOG:  autovacuum launcher started
go-oauth2-server exited with code 1

go-docker-oath2 container exits right away

docker ps

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
48e69da5974b        elcolio/etcd        "/bin/run.sh"            35 minutes ago      Up 15 minutes       2379-2380/tcp, 4001/tcp, 7001/tcp   gooauth2server_etcd_1
c4afdcde5778        postgres            "/docker-entrypoint.s"   35 minutes ago      Up 15 minutes       5432/tcp                            gooauth2server_postgres_1

docker ps -a

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                               NAMES
48e69da5974b        elcolio/etcd        "/bin/run.sh"            35 minutes ago      Up 15 minutes       2379-2380/tcp, 4001/tcp, 7001/tcp   gooauth2server_etcd_1
c4afdcde5778        postgres            "/docker-entrypoint.s"   35 minutes ago      Up 15 minutes       5432/tcp                            gooauth2server_postgres_1
50fa78b40360        go-oauth2-server          "/docker-entrypoint.s"   9 minutes ago        Exited (0) 8 minutes ago                                            furious_mayer

1) In memory sessions; and 2) user log out

Hi Richard,

First, great library. I've been exploring it for the past few days and I really like it. Thanks for the great work!

Second, two quick questions:

  1. You're storing configs in etcd or consul, but it appears that sessions are being stored in memory s.session.Values? Any reason you chose not to store sessions in etcd or consul?
  2. When a user logs out, you clear the sessions. However, any access / refresh tokens granted on the user's behalf are not affected. This means that anyone with an auth token can continue making requests on the user's behalf. I understand that it's outside of oAuth 2.0's scope to define sessions / what happens when a user logs out but what are your thoughts on how log out should affect tokens? Maybe both access and refresh tokens should be revoked? Or maybe there should be a check against user session when a token is being refreshed?

Cheers!

JWT Integration

Do you have any plans to integrate JWT as an optional token medium?

ctx is attached with a deadline is exceeded: context deadline exceeded

Hello,
i am on Windows 8 with golang env installed , I have cloned the go-oauth2-server , i have postgresql latest installed , now i run fo-oauth2-server migrate it i sshowing me error "*ctx is attached with a deadline is exceeded: context deadline exceeded"
I have created "go-oauth2-server" DB and user through pgadmin3 , what extra steps i have to take .
I want to run this and test it locally first which later will be deployed as microservice on docker

Please help

Audit?

Has there been an audit of the code base?

Is there a plan to support the management interface

I think go-oauth2-server is a very good project, is there a plan to support the management interface and some Rest API to go-oauth2-server like user role management ? If have these functions, other services can no longer consider user management, role management such a basic module(`・ω・´)

Store Abstraction + Redis Session Store

I worked today on abstracting this code base a little bit. I only really made one change: moving the session.NewService out of web/middlewares.go and into cmd/util.go. After that it was super easy to implement any of the many Gorilla store implementations.

Here's the abstracted code. It uses an in-memory service as a default.

Here's an implementation of using a redis "plugin" to store sessions.

I'm not sure if I'm totally happy with how the abstraction turned out. I'll try to think of cleaner ways of doing it. I may merge this into the uuid branch and submit a PR, if you'd like.

combine efforts with Dex project?

Hello Richard-

I can't find your email so I am filing an issue.

Is there a reason you are building this project instead of using Dex: github.com/coreos/dex? I noticed this project started recently so maybe you didn't stumble upon Dex.

Dex implements OAUTH2.0 and OpenID connect and I have started integrating it and testing it against different projects like Kubernetes and Bitly's oauth2_proxy project.

Cheers,

Brandon
[email protected]

cc @bobbyrullo

could you provide more documentation or a sample for the "docker compose" section?

Sorry I'm a docker newb trying to get an environment setup that will let me run end-to-end tests of a web application. I am excited to use docker to create a test environment where I can put in a real SMTP and OAuth2 server to verify interactions with such services.

I have all the services running except OAuth2 :(. Sorry I could really follow the instructions. I tried the naive thing in my docker-compose file:

services:
  ...
  go-oauth2:
    image: "richardknop/go-oauth2-server"
    ports:
     - "8082:8080"    

and I get the following output:

go-oauth2_1      | Postgres is up - executing command: 
go-oauth2_1      | NAME:
go-oauth2_1      |    go-oauth2-server - Go OAuth 2.0 Server
go-oauth2_1      | 
go-oauth2_1      | USAGE:
go-oauth2_1      |    go-oauth2-server [global options] command [command options] [arguments...]
go-oauth2_1      | 
go-oauth2_1      | VERSION:
go-oauth2_1      |    0.0.0
go-oauth2_1      | 
go-oauth2_1      | AUTHOR:
go-oauth2_1      |    Richard Knop <[email protected]>
go-oauth2_1      | 
go-oauth2_1      | COMMANDS:
go-oauth2_1      |      migrate    run migrations
go-oauth2_1      |      loaddata   load data from fixture
go-oauth2_1      |      runserver  run web server
go-oauth2_1      |      help, h    Shows a list of commands or help for one command
go-oauth2_1      | 
go-oauth2_1      | GLOBAL OPTIONS:
go-oauth2_1      |    --configBackend value  (default: "etcd")
go-oauth2_1      |    --help, -h             show help
go-oauth2_1      |    --version, -v          print the version

I'm guessing it didn't work because usually CLI apps give the help output when they don't know what to do. Once I get it running I'll need to figure out how to setup test users.

docker-compose up fails

What?

On doing docker-compose up it fails.

 ---> Running in d493c374f60e
# github.com/RichardKnop/go-oauth2-server/vendor/github.com/coreos/etcd/clientv3
vendor/github.com/coreos/etcd/clientv3/client.go:336:9: undefined: metadata.NewContext
vendor/github.com/coreos/etcd/clientv3/lease.go:326:14: undefined: metadata.FromContext
ERROR: Service 'app_testdata' failed to build: The command '/bin/sh -c go install github.com/RichardKnop/go-oauth2-server' returned a non-zero code: 2

how can i add new one client id

in the test samples have two client id,test_client_1,test_client_2 and passwords.
how can i add new one client id?
thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.