oauth2: add support for client credential grant type

Creates a new package called clientcredentials and
adds transport and token information to the internal
package. Also modifies the oauth2 package to make
use of the newly added files in the internal package.

The clientcredentials package allows for token requests
using a "client credentials" grant type.

Fixes https://github.com/golang/oauth2/issues/7

Change-Id: Iec649d1029870c27a2d1023baa9d52db42ff45e8
Reviewed-on: https://go-review.googlesource.com/2983
Reviewed-by: Burcu Dogan <jbd@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Aaron Torres
2015-01-16 14:43:33 -08:00
committed by Burcu Dogan
parent ce5ea7da93
commit a8c019d04a
11 changed files with 562 additions and 249 deletions

View File

@@ -0,0 +1,96 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package clientcredentials
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
"golang.org/x/oauth2"
)
func newConf(url string) *Config {
return &Config{
ClientID: "CLIENT_ID",
ClientSecret: "CLIENT_SECRET",
Scopes: []string{"scope1", "scope2"},
TokenURL: url + "/token",
}
}
type mockTransport struct {
rt func(req *http.Request) (resp *http.Response, err error)
}
func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
return t.rt(req)
}
func TestTokenRequest(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.String() != "/token" {
t.Errorf("authenticate client request URL = %q; want %q", r.URL, "/token")
}
headerAuth := r.Header.Get("Authorization")
if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
}
if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
t.Errorf("Content-Type header = %q; want %q", got, want)
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
r.Body.Close()
}
if err != nil {
t.Errorf("failed reading request body: %s.", err)
}
if string(body) != "client_id=CLIENT_ID&grant_type=client_credentials&scope=scope1+scope2" {
t.Errorf("payload = %q; want %q", string(body), "client_id=CLIENT_ID&grant_type=client_credentials&scope=scope1+scope2")
}
w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
w.Write([]byte("access_token=90d64460d14870c08c81352a05dedd3465940a7c&token_type=bearer"))
}))
defer ts.Close()
conf := newConf(ts.URL)
tok, err := conf.Token(oauth2.NoContext)
if err != nil {
t.Error(err)
}
if !tok.Valid() {
t.Fatalf("token invalid. got: %#v", tok)
}
if tok.AccessToken != "90d64460d14870c08c81352a05dedd3465940a7c" {
t.Errorf("Access token = %q; want %q", tok.AccessToken, "90d64460d14870c08c81352a05dedd3465940a7c")
}
if tok.TokenType != "bearer" {
t.Errorf("token type = %q; want %q", tok.TokenType, "bearer")
}
}
func TestTokenRefreshRequest(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.String() == "/somethingelse" {
return
}
if r.URL.String() != "/token" {
t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
}
headerContentType := r.Header.Get("Content-Type")
if headerContentType != "application/x-www-form-urlencoded" {
t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
}
body, _ := ioutil.ReadAll(r.Body)
if string(body) != "client_id=CLIENT_ID&grant_type=client_credentials&scope=scope1+scope2" {
t.Errorf("Unexpected refresh token payload, %v is found.", string(body))
}
}))
defer ts.Close()
conf := newConf(ts.URL)
c := conf.Client(oauth2.NoContext)
c.Get(ts.URL + "/somethingelse")
}