Stark & Wayne

Simple Golang OAuth client for Cloud Foundry

Cloud Foundry UAA allows OAuth clients to be used to leverage the users of Cloud Foundry. This allows you to create apps without maintaining another user database. A free single-signon (SSO) for all your applications!

Golang makes it easy to write applications that use SSO - by being OAuth clients for UAA (and your pretty/themed login-server).

First we need to add client into UAA client

      cf-go-client-example:
        access-token-validity: 1209600
        authorities: scim.write,scim.read,cloud_controller.read,cloud_controller.write,password.write,uaa.admin,uaa.resource,cloud_controller.admin,billing.admin
        authorized-grant-types: authorization_code,client_credentials
        override: true
        redirect-uri: https://cf-go-client-example.10.244.0.34.xip.io/oauth2callback
        refresh-token-validity: 1209600
        scope: openid,cloud_controller.read,cloud_controller.write,password.write,console.admin,console.support
        secret: c1oudc0w

Please note the authorizations example exposes many scopes & authorities. You can scope it back for your use cases.

main.go

package main
 
import (
	"github.com/go-martini/martini"
	gooauth2 "github.com/golang/oauth2"
	"github.com/martini-contrib/oauth2"
	"github.com/martini-contrib/sessions"
)
 
func main() {
	m := martini.Classic()
 
	oauthOpts := &gooauth2.Options{
		ClientID:     "cf-go-client-example",
		ClientSecret: "c1oudc0w",
		RedirectURL:  "https://cf-go-client-example.10.244.0.34.xip.io/oauth2callback",
		Scopes:       []string{""},
	}
 
	cf := oauth2.NewOAuth2Provider(oauthOpts, "https://login.10.244.0.34.xip.io/oauth/authorize",
		"https://uaa.10.244.0.34.xip.io/oauth/token")
 
	m.Handlers(
		sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))),
		cf,
		oauth2.LoginRequired,
		martini.Logger(),
		martini.Static("public"),
	)
 
	m.Get("/", func(tokens oauth2.Tokens) string {
		if tokens.IsExpired() {
			return "not logged in, or the access token is expired"
		}
		return "logged in"
	})
 
	m.Run()
}

That's it! Simple as that.

m := martini.Classic()

We use martini for this because it has great plugin.

oauthOpts := &gooauth2.Options{
		ClientID:     "cf-go-client-example",
		ClientSecret: "c1oudc0w",
		RedirectURL:  "https://cf-go-client-example.10.244.0.34.xip.io/oauth2callback",
		Scopes:       []string{""},
	}
 
	cf := oauth2.NewOAuth2Provider(oauthOpts, "https://login.10.244.0.34.xip.io/oauth/authorize",
		"https://uaa.10.244.0.34.xip.io/oauth/token")

This setup our OAuth handler. Note that redirect URL must match the one set in manifest or it will not work.

m.Handlers(
		sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))),
		cf,
		oauth2.LoginRequired,
		martini.Logger(),
		martini.Static("public"),
	)

These handlers force all connections to be authenticated. The session is needed to keep a session for each user.

	m.Get("/restrict", oauth2.LoginRequired, func(tokens oauth2.Tokens) string {
		return tokens.Access()
	})

Alternately if you don't want all request to be authenticated, you can do it by endpoint. With martini you can chain handler.

	m.Get("/", func(tokens oauth2.Tokens) string {
		if tokens.IsExpired() {
			return "not logged in, or the access token is expired"
		}
		return "logged in"
	})
 
	m.Run()

That's it you have an OAuth client for Cloud Foundry.

The code can be found: https://github.com/cloudfoundry-community/cf-go-client-example