Awesome Open Source
Awesome Open Source

Identity Provider (IdP) for Hydra

Build Status Code Climate GoDoc Gitter

This is a helper library for handling challenge requests from Hydra, it handles:

  • Storing challenge in a short lived cookie instead of query parameters
  • Passing user's consent to Hydra
  • Retriving keys from Hydra and using them for JWT verification
  • Caching keys and client info

IdP uses Gorilla sessions as the Store. There are many Gorilla sessions backend implementations out there.

About

Let's say we have an Identity Provider with:

  • /login endpoint that accepts Hydra's challenges
  • /consent endpoint that handles getting consent from the user

This is how challenge request could be hadled with the IdP library:

Sequence Diagram

Initialization

There are many implementations of Gorilla sessions. Let's use Postgres as the backend:

import (
	"github.com/janekolszak/idp"
	"github.com/antonlindstrom/pgstore"
	"time"
)

func main() {
	challengeCookieStore, err = pgstore.NewPGStore("postgres://user:[email protected]/dbname", []byte("secret"))
	// Return on error

	// Create the IDP
	IDP := idp.NewIDP(&idp.IDPConfig{
		ClusterURL:            /* Hydra's address */,
		ClientID:              /* IDP's client ID */,
		ClientSecret:          /* IDP's client secret */,
		KeyCacheExpiration:    time.Duration(/* Key expiration time */) * time.Second,
		ClientCacheExpiration: time.Duration(/* Client info expiration */) * time.Second,
		CacheCleanupInterval:  time.Duration(/* Cache cleanup interval. Eg. 30 */) * time.Second,
		ChallengeExpiration:   time.Duration(/* Challenge cookie expiration. Eg. 10 */) * time.Minutes,
		ChallengeStore:        challengeCookieStore,
	})

	// Connects with Hydra and fills caches
	err = IDP.Connect(true /*TLS verification*/)
	// Return on error

}

Usage


func HandleChallengeGET(w http.ResponseWriter, r *http.Request) {
	// 0. Render HTML page with a login form
}

func HandleChallengePOST(w http.ResponseWriter, r *http.Request) {
	// 0. Parse and validate login data (username:password, login cookie etc)
	//    Return on error

	// 1. Verify user's credentials (eg. check username:password).
	//    Return on error
	//    Obtain userid

	// 2. Create a Challenge
	challenge, err := IDP.NewChallenge(r, userid)
	//    Return on error

	// 3. Save the Challenge to a cookie with a small TTL
	err = challenge.Save(w, r)
	//    Return on error

	// 4. Redirect to the consent endpoint
}

// Displays Consent screen. Here user agrees for listed scopes
func HandleConsentGET(w http.ResponseWriter, r *http.Request) {

	// 0. Get the Challenge from the cookie
	challenge, err := IDP.GetChallenge(r)
	//    Return on error

	// 1. Display consent screen
	//    Use challenge.User to get user's ID
	//    Use challenge.Scopes to display requested scopes

	// 2. If any error occured delete the Challenge cookie (optional)
	if err != nil {
		err = challenge.Delete(c.Writer, c.Request)
	}

	// 3. Render the HTML consent page
}

func HandleConsentPOST(w http.ResponseWriter, r *http.Request) {
	// 0. Get the Challenge from the cookie
	challenge, err := IDP.GetChallenge(c.Request)
	//    Return on error

	// 1. Parse and validate consent data (eg. form answer=y or list of scopes)
	//    Return on error

	// 2. If user refused access
	err = challenge.RefuseAccess(w, r)
	//    Return

	// 3. If userf agreed to grant access
	err = challenge.GrantAccessToAll(w, r)
	//    Return
}

Alternatives To Idp
Select To Compare


Alternative Project Comparisons
Related Awesome Lists
Top Programming Languages
Top Projects

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
Go (163,556
Provider (15,514
Session (14,152
Identity (5,918
Hydra (960
Idp (872
Gorilla (621
Identity Provider (301