hanayo/vendor/github.com/RangelReale/osin/access_test.go
2019-02-23 13:29:15 +00:00

490 lines
13 KiB
Go

package osin
import (
"net/http"
"net/url"
"testing"
"time"
)
func TestAccessAuthorizationCode(t *testing.T) {
sconfig := NewServerConfig()
sconfig.AllowedAccessTypes = AllowedAccessType{AUTHORIZATION_CODE}
server := NewServer(sconfig, NewTestingStorage())
server.AccessTokenGen = &TestingAccessTokenGen{}
resp := server.NewResponse()
req, err := http.NewRequest("POST", "http://localhost:14000/appauth", nil)
if err != nil {
t.Fatal(err)
}
req.SetBasicAuth("1234", "aabbccdd")
req.Form = make(url.Values)
req.Form.Set("grant_type", string(AUTHORIZATION_CODE))
req.Form.Set("code", "9999")
req.Form.Set("state", "a")
req.PostForm = make(url.Values)
if ar := server.HandleAccessRequest(resp, req); ar != nil {
ar.Authorized = true
server.FinishAccessRequest(resp, req, ar)
}
//fmt.Printf("%+v", resp)
if resp.IsError && resp.InternalError != nil {
t.Fatalf("Error in response: %s", resp.InternalError)
}
if resp.IsError {
t.Fatalf("Should not be an error")
}
if resp.Type != DATA {
t.Fatalf("Response should be data")
}
if d := resp.Output["access_token"]; d != "1" {
t.Fatalf("Unexpected access token: %s", d)
}
if d := resp.Output["refresh_token"]; d != "r1" {
t.Fatalf("Unexpected refresh token: %s", d)
}
}
func TestAccessRefreshToken(t *testing.T) {
sconfig := NewServerConfig()
sconfig.AllowedAccessTypes = AllowedAccessType{REFRESH_TOKEN}
server := NewServer(sconfig, NewTestingStorage())
server.AccessTokenGen = &TestingAccessTokenGen{}
resp := server.NewResponse()
req, err := http.NewRequest("POST", "http://localhost:14000/appauth", nil)
if err != nil {
t.Fatal(err)
}
req.SetBasicAuth("1234", "aabbccdd")
req.Form = make(url.Values)
req.Form.Set("grant_type", string(REFRESH_TOKEN))
req.Form.Set("refresh_token", "r9999")
req.Form.Set("state", "a")
req.PostForm = make(url.Values)
if ar := server.HandleAccessRequest(resp, req); ar != nil {
ar.Authorized = true
server.FinishAccessRequest(resp, req, ar)
}
//fmt.Printf("%+v", resp)
if _, err := server.Storage.LoadRefresh("r9999"); err == nil {
t.Fatalf("token was not deleted")
}
if resp.IsError && resp.InternalError != nil {
t.Fatalf("Error in response: %s", resp.InternalError)
}
if resp.IsError {
t.Fatalf("Should not be an error")
}
if resp.Type != DATA {
t.Fatalf("Response should be data")
}
if d := resp.Output["access_token"]; d != "1" {
t.Fatalf("Unexpected access token: %s", d)
}
if d := resp.Output["refresh_token"]; d != "r1" {
t.Fatalf("Unexpected refresh token: %s", d)
}
}
func TestAccessRefreshTokenSaveToken(t *testing.T) {
sconfig := NewServerConfig()
sconfig.AllowedAccessTypes = AllowedAccessType{REFRESH_TOKEN}
server := NewServer(sconfig, NewTestingStorage())
server.AccessTokenGen = &TestingAccessTokenGen{}
server.Config.RetainTokenAfterRefresh = true
resp := server.NewResponse()
req, err := http.NewRequest("POST", "http://localhost:14000/appauth", nil)
if err != nil {
t.Fatal(err)
}
req.SetBasicAuth("1234", "aabbccdd")
req.Form = make(url.Values)
req.Form.Set("grant_type", string(REFRESH_TOKEN))
req.Form.Set("refresh_token", "r9999")
req.Form.Set("state", "a")
req.PostForm = make(url.Values)
if ar := server.HandleAccessRequest(resp, req); ar != nil {
ar.Authorized = true
server.FinishAccessRequest(resp, req, ar)
}
//fmt.Printf("%+v", resp)
if _, err := server.Storage.LoadRefresh("r9999"); err != nil {
t.Fatalf("token incorrectly deleted: %s", err.Error())
}
if resp.IsError && resp.InternalError != nil {
t.Fatalf("Error in response: %s", resp.InternalError)
}
if resp.IsError {
t.Fatalf("Should not be an error")
}
if resp.Type != DATA {
t.Fatalf("Response should be data")
}
if d := resp.Output["access_token"]; d != "1" {
t.Fatalf("Unexpected access token: %s", d)
}
if d := resp.Output["refresh_token"]; d != "r1" {
t.Fatalf("Unexpected refresh token: %s", d)
}
}
func TestAccessPassword(t *testing.T) {
sconfig := NewServerConfig()
sconfig.AllowedAccessTypes = AllowedAccessType{PASSWORD}
server := NewServer(sconfig, NewTestingStorage())
server.AccessTokenGen = &TestingAccessTokenGen{}
resp := server.NewResponse()
req, err := http.NewRequest("POST", "http://localhost:14000/appauth", nil)
if err != nil {
t.Fatal(err)
}
req.SetBasicAuth("1234", "aabbccdd")
req.Form = make(url.Values)
req.Form.Set("grant_type", string(PASSWORD))
req.Form.Set("username", "testing")
req.Form.Set("password", "testing")
req.Form.Set("state", "a")
req.PostForm = make(url.Values)
if ar := server.HandleAccessRequest(resp, req); ar != nil {
ar.Authorized = ar.Username == "testing" && ar.Password == "testing"
server.FinishAccessRequest(resp, req, ar)
}
//fmt.Printf("%+v", resp)
if resp.IsError && resp.InternalError != nil {
t.Fatalf("Error in response: %s", resp.InternalError)
}
if resp.IsError {
t.Fatalf("Should not be an error")
}
if resp.Type != DATA {
t.Fatalf("Response should be data")
}
if d := resp.Output["access_token"]; d != "1" {
t.Fatalf("Unexpected access token: %s", d)
}
if d := resp.Output["refresh_token"]; d != "r1" {
t.Fatalf("Unexpected refresh token: %s", d)
}
}
func TestAccessClientCredentials(t *testing.T) {
sconfig := NewServerConfig()
sconfig.AllowedAccessTypes = AllowedAccessType{CLIENT_CREDENTIALS}
server := NewServer(sconfig, NewTestingStorage())
server.AccessTokenGen = &TestingAccessTokenGen{}
resp := server.NewResponse()
req, err := http.NewRequest("POST", "http://localhost:14000/appauth", nil)
if err != nil {
t.Fatal(err)
}
req.SetBasicAuth("1234", "aabbccdd")
req.Form = make(url.Values)
req.Form.Set("grant_type", string(CLIENT_CREDENTIALS))
req.Form.Set("state", "a")
req.PostForm = make(url.Values)
if ar := server.HandleAccessRequest(resp, req); ar != nil {
ar.Authorized = true
server.FinishAccessRequest(resp, req, ar)
}
//fmt.Printf("%+v", resp)
if resp.IsError && resp.InternalError != nil {
t.Fatalf("Error in response: %s", resp.InternalError)
}
if resp.IsError {
t.Fatalf("Should not be an error")
}
if resp.Type != DATA {
t.Fatalf("Response should be data")
}
if d := resp.Output["access_token"]; d != "1" {
t.Fatalf("Unexpected access token: %s", d)
}
if d, dok := resp.Output["refresh_token"]; dok {
t.Fatalf("Refresh token should not be generated: %s", d)
}
}
func TestExtraScopes(t *testing.T) {
if extraScopes("", "") == true {
t.Fatalf("extraScopes returned true with empty scopes")
}
if extraScopes("a", "") == true {
t.Fatalf("extraScopes returned true with less scopes")
}
if extraScopes("a,b", "b,a") == true {
t.Fatalf("extraScopes returned true with matching scopes")
}
if extraScopes("a,b", "b,a,c") == false {
t.Fatalf("extraScopes returned false with extra scopes")
}
if extraScopes("", "a") == false {
t.Fatalf("extraScopes returned false with extra scopes")
}
}
// clientWithoutMatcher just implements the base Client interface
type clientWithoutMatcher struct {
Id string
Secret string
RedirectUri string
}
func (c *clientWithoutMatcher) GetId() string { return c.Id }
func (c *clientWithoutMatcher) GetSecret() string { return c.Secret }
func (c *clientWithoutMatcher) GetRedirectUri() string { return c.RedirectUri }
func (c *clientWithoutMatcher) GetUserData() interface{} { return nil }
func TestGetClientWithoutMatcher(t *testing.T) {
myclient := &clientWithoutMatcher{
Id: "myclient",
Secret: "myclientsecret",
RedirectUri: "http://www.example.com",
}
storage := &TestingStorage{clients: map[string]Client{myclient.Id: myclient}}
// Ensure bad secret fails
{
auth := &BasicAuth{
Username: "myclient",
Password: "invalidsecret",
}
w := &Response{}
client := getClient(auth, storage, w)
if client != nil {
t.Errorf("Expected error, got client: %v", client)
}
if !w.IsError {
t.Error("No error in response")
}
if w.ErrorId != E_UNAUTHORIZED_CLIENT {
t.Errorf("Expected error %v, got %v", E_UNAUTHORIZED_CLIENT, w.ErrorId)
}
}
// Ensure nonexistent client fails
{
auth := &BasicAuth{
Username: "nonexistent",
Password: "nonexistent",
}
w := &Response{}
client := getClient(auth, storage, w)
if client != nil {
t.Errorf("Expected error, got client: %v", client)
}
if !w.IsError {
t.Error("No error in response")
}
if w.ErrorId != E_UNAUTHORIZED_CLIENT {
t.Errorf("Expected error %v, got %v", E_UNAUTHORIZED_CLIENT, w.ErrorId)
}
}
// Ensure good secret works
{
auth := &BasicAuth{
Username: "myclient",
Password: "myclientsecret",
}
w := &Response{}
client := getClient(auth, storage, w)
if client != myclient {
t.Errorf("Expected client, got nil with response: %v", w)
}
}
}
// clientWithMatcher implements the base Client interface and the ClientSecretMatcher interface
type clientWithMatcher struct {
Id string
Secret string
RedirectUri string
}
func (c *clientWithMatcher) GetId() string { return c.Id }
func (c *clientWithMatcher) GetSecret() string { panic("called GetSecret"); return "" }
func (c *clientWithMatcher) GetRedirectUri() string { return c.RedirectUri }
func (c *clientWithMatcher) GetUserData() interface{} { return nil }
func (c *clientWithMatcher) ClientSecretMatches(secret string) bool {
return secret == c.Secret
}
func TestGetClientSecretMatcher(t *testing.T) {
myclient := &clientWithMatcher{
Id: "myclient",
Secret: "myclientsecret",
RedirectUri: "http://www.example.com",
}
storage := &TestingStorage{clients: map[string]Client{myclient.Id: myclient}}
// Ensure bad secret fails, but does not panic (doesn't call GetSecret)
{
auth := &BasicAuth{
Username: "myclient",
Password: "invalidsecret",
}
w := &Response{}
client := getClient(auth, storage, w)
if client != nil {
t.Errorf("Expected error, got client: %v", client)
}
}
// Ensure good secret works, but does not panic (doesn't call GetSecret)
{
auth := &BasicAuth{
Username: "myclient",
Password: "myclientsecret",
}
w := &Response{}
client := getClient(auth, storage, w)
if client != myclient {
t.Errorf("Expected client, got nil with response: %v", w)
}
}
}
func TestAccessAuthorizationCodePKCE(t *testing.T) {
testcases := map[string]struct {
Challenge string
ChallengeMethod string
Verifier string
ExpectedError string
}{
"good, plain": {
Challenge: "12345678901234567890123456789012345678901234567890",
Verifier: "12345678901234567890123456789012345678901234567890",
},
"bad, plain": {
Challenge: "12345678901234567890123456789012345678901234567890",
Verifier: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
ExpectedError: "invalid_grant",
},
"good, S256": {
Challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
ChallengeMethod: "S256",
Verifier: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
},
"bad, S256": {
Challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
ChallengeMethod: "S256",
Verifier: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
ExpectedError: "invalid_grant",
},
"missing from storage": {
Challenge: "",
ChallengeMethod: "",
Verifier: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
},
}
for k, test := range testcases {
testStorage := NewTestingStorage()
sconfig := NewServerConfig()
sconfig.AllowedAccessTypes = AllowedAccessType{AUTHORIZATION_CODE}
server := NewServer(sconfig, testStorage)
server.AccessTokenGen = &TestingAccessTokenGen{}
server.Storage.SaveAuthorize(&AuthorizeData{
Client: testStorage.clients["public-client"],
Code: "pkce-code",
ExpiresIn: 3600,
CreatedAt: time.Now(),
RedirectUri: "http://localhost:14000/appauth",
CodeChallenge: test.Challenge,
CodeChallengeMethod: test.ChallengeMethod,
})
resp := server.NewResponse()
req, err := http.NewRequest("POST", "http://localhost:14000/appauth", nil)
if err != nil {
t.Fatal(err)
}
req.SetBasicAuth("public-client", "")
req.Form = make(url.Values)
req.Form.Set("grant_type", string(AUTHORIZATION_CODE))
req.Form.Set("code", "pkce-code")
req.Form.Set("state", "a")
req.Form.Set("code_verifier", test.Verifier)
req.PostForm = make(url.Values)
if ar := server.HandleAccessRequest(resp, req); ar != nil {
ar.Authorized = true
server.FinishAccessRequest(resp, req, ar)
}
if resp.IsError {
if test.ExpectedError == "" || test.ExpectedError != resp.ErrorId {
t.Errorf("%s: unexpected error: %v, %v", k, resp.ErrorId, resp.StatusText)
continue
}
}
if test.ExpectedError == "" {
if resp.Type != DATA {
t.Fatalf("%s: Response should be data", k)
}
if d := resp.Output["access_token"]; d != "1" {
t.Fatalf("%s: Unexpected access token: %s", k, d)
}
if d := resp.Output["refresh_token"]; d != "r1" {
t.Fatalf("%s: Unexpected refresh token: %s", k, d)
}
}
}
}