Пример #1
0
func TestAuthValidateCodeResponseAuthenticateOk(t *testing.T) {

	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	var loginCalled = false
	ls := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		loginCalled = true
		w.WriteHeader(http.StatusOK)
	}))
	defer ls.Close()

	//TODO - use a second callback where we serve up a script to extract the page details sent
	//on deny and post those details to another test server.
	var callbackInvoked = false

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		callbackInvoked = true
		code := r.FormValue("code")
		token, err := jwt.Parse(code, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
		assert.Nil(t, err)
		scope, ok := token.Claims["scope"].(string)
		assert.True(t, ok)
		assert.Equal(t, "xtAuthCode", scope)
	}))
	defer ts.Close()

	lsURL, _ := url.Parse(ls.URL)

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     ts.URL,
		LoginProvider:   "xtrac://" + lsURL.Host,
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	_, err = http.PostForm(addr+"/oauth2/validate",
		url.Values{"username": {"x"},
			"password":      {"y"},
			"authorize":     {"allow"},
			"response_type": {"code"},
			"client_id":     {"1111-2222-3333333-4444444"}})
	assert.Nil(t, err)
	assert.True(t, callbackInvoked)
	assert.True(t, loginCalled)
}
Пример #2
0
func TestPWGrantLoginOk(t *testing.T) {
	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	var loginCalled = false
	ls := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		loginCalled = true
		w.WriteHeader(http.StatusOK)
	}))
	defer ls.Close()

	lsURL, _ := url.Parse(ls.URL)

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     "http://localhost:3000/ab",
		LoginProvider:   "xtrac://" + lsURL.Host,
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	resp, err := http.PostForm(addr+OAuth2TokenBaseURI,
		url.Values{"grant_type": {"password"},
			"client_id":     {"1111-2222-3333333-4444444"},
			"client_secret": {"not for browser clients"},
			"username":      {"abc"},
			"password":      {"xxxxxxxx"}})

	assert.True(t, loginCalled)
	assert.Nil(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)

	body := responseAsString(t, resp)
	var jsonResponse accessTokenResponse
	err = json.Unmarshal([]byte(body), &jsonResponse)
	assert.Nil(t, err)
	assert.True(t, jsonResponse.AccessToken != "")
	assert.True(t, jsonResponse.TokenType == "Bearer")

	token, err := jwt.Parse(jsonResponse.AccessToken, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
	assert.Nil(t, err)
	fmt.Println(token.Claims)
	assert.Equal(t, "1111-2222-3333333-4444444", token.Claims["aud"].(string))
	assert.Equal(t, "abc", token.Claims["sub"].(string))
	assert.Equal(t, "", token.Claims["scope"].(string))
}
Пример #3
0
func TestAuthValidateCodeResponseAuthenticateAdminScopeError(t *testing.T) {

	var loginCalled = false
	ls := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		loginCalled = true
		w.WriteHeader(http.StatusOK)
	}))
	defer ls.Close()

	//TODO - use a second callback where we serve up a script to extract the page details sent
	//on deny and post those details to another test server.
	var callbackInvoked = false

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		callbackInvoked = true
		assert.True(t, strings.Contains(r.RequestURI, "error=server_error&error_description="))
	}))
	defer ts.Close()

	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	lsURL, _ := url.Parse(ls.URL)

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     ts.URL + "/foo",
		LoginProvider:   "xtrac://" + lsURL.Host,
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	adminRepoMock := coreConfig.AdminRepo.(*mocks.AdminRepo)
	adminRepoMock.On("IsAdmin", "x").Return(false, errors.New("BOOM!"))

	privateKey, _, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)

	_, err = http.PostForm(addr+"/oauth2/validate",
		url.Values{"username": {"x"},
			"password":      {"y"},
			"authorize":     {"allow"},
			"response_type": {"code"},
			"scope":         {"admin"},
			"client_id":     {"1111-2222-3333333-4444444"}})
	assert.Nil(t, err)
	assert.True(t, callbackInvoked)
}
Пример #4
0
func TestTokenSignedWithWrongKey(t *testing.T) {
	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     "http://localhost:3000/ab",
		LoginProvider:   "xtrac://localhost:9000",
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	otherKey, _, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	code, err := rolltoken.GenerateCode("a-subject", "", returnVal.ClientID, otherKey)
	assert.Nil(t, err)

	resp, err := http.PostForm(addr+OAuth2TokenBaseURI,
		url.Values{"grant_type": {"authorization_code"},
			"client_id":     {"1111-2222-3333333-4444444"},
			"client_secret": {"not for browser clients"},
			"redirect_uri":  {"http://localhost:3000/ab"},
			"code":          {code}})

	assert.Nil(t, err)
	body := responseAsString(t, resp)
	assert.True(t, strings.Contains(body, "verification error"))
	assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
}
Пример #5
0
func TestInvalidSignature(t *testing.T) {
	app := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     "http://localhost:3000/ab",
		LoginProvider:   "xtrac://localhost:9000",
	}

	appRepoMock := new(mocks.ApplicationRepo)
	appRepoMock.On("RetrieveApplication", "1111-2222-3333333-4444444").Return(&app, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	private2, _, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := new(mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	adminRepo := new(mocks.AdminRepo)

	token, err := rolltoken.GenerateToken("b-subject", "", app.ClientID, app.ApplicationName, private2)
	assert.Nil(t, err)

	testServer := httptest.NewServer(Wrap(secretsMock, adminRepo, []string{}, echoHandler()))
	defer testServer.Close()

	client := http.Client{}
	req, err := http.NewRequest("POST", testServer.URL, nil)
	assert.Nil(t, err)
	req.Header.Add("Authorization", "Bearer "+token)

	resp, err := client.Do(req)
	assert.Nil(t, err)
	assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
}
Пример #6
0
func TestTokenValidCodeWithAdminScope(t *testing.T) {
	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     "http://localhost:3000/ab",
		LoginProvider:   "xtrac://localhost:9000",
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	code, err := rolltoken.GenerateCode("b-subject", "admin", returnVal.ClientID, privateKey)
	assert.Nil(t, err)

	resp, err := http.PostForm(addr+OAuth2TokenBaseURI,
		url.Values{"grant_type": {"authorization_code"},
			"client_id":     {"1111-2222-3333333-4444444"},
			"client_secret": {"not for browser clients"},
			"redirect_uri":  {"http://localhost:3000/ab"},
			"code":          {code}})

	assert.Nil(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
	body := responseAsString(t, resp)

	var jsonResponse accessTokenResponse
	err = json.Unmarshal([]byte(body), &jsonResponse)
	assert.Nil(t, err)
	assert.True(t, jsonResponse.AccessToken != "")
	assert.True(t, jsonResponse.TokenType == "Bearer")

	token, err := jwt.Parse(jsonResponse.AccessToken, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
	assert.Nil(t, err)
	scope, ok := token.Claims["scope"].(string)
	assert.True(t, ok)
	assert.Equal(t, "admin", scope)

}
Пример #7
0
func TestPWGrantLoginOkInvalidScope(t *testing.T) {
	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	var loginCalled = false
	ls := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		loginCalled = true
		w.WriteHeader(http.StatusOK)
	}))
	defer ls.Close()

	lsURL, _ := url.Parse(ls.URL)

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     "http://localhost:3000/ab",
		LoginProvider:   "xtrac://" + lsURL.Host,
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	adminRepoMock := coreConfig.AdminRepo.(*mocks.AdminRepo)
	adminRepoMock.On("IsAdmin", "abc").Return(true, nil)

	resp, err := http.PostForm(addr+OAuth2TokenBaseURI,
		url.Values{"grant_type": {"password"},
			"client_id":     {"1111-2222-3333333-4444444"},
			"client_secret": {"not for browser clients"},
			"username":      {"abc"},
			"scope":         {"adminxxx"},
			"password":      {"xxxxxxxx"}})

	assert.True(t, loginCalled)
	assert.Nil(t, err)
	assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)

}
Пример #8
0
func TestJWTFlowValidAssertionOkYeah(t *testing.T) {
	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	returnVal := roll.Application{
		DeveloperEmail:   "*****@*****.**",
		ClientID:         "1111-2222-3333333-4444444",
		ApplicationName:  "fight club",
		ClientSecret:     "not for browser clients",
		RedirectURI:      "http://localhost:3000/ab",
		LoginProvider:    "xtrac://localhost:9000",
		JWTFlowPublicKey: publicKey,
		JWTFlowIssuer:    "1111-2222-3333333-4444444",
		JWTFlowAudience:  "captive",
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplicationByJWTFlowAudience", "captive").Return(&returnVal, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	resp, err := http.PostForm(addr+OAuth2TokenBaseURI,
		url.Values{"grant_type": {"urn:ietf:params:oauth:grant-type:jwt-bearer"},
			"assertion": {jwtAssertion}})

	assert.Nil(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
	bodyStr := responseAsString(t, resp)
	println(bodyStr)

	var jsonResponse accessTokenResponse
	err = json.Unmarshal([]byte(bodyStr), &jsonResponse)
	assert.Nil(t, err)
	assert.True(t, jsonResponse.AccessToken != "")
	assert.True(t, jsonResponse.TokenType == "Bearer")

	token, err := jwt.Parse(jsonResponse.AccessToken, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
	assert.Nil(t, err)
	assert.Equal(t, "1111-2222-3333333-4444444", token.Claims["aud"].(string))
	assert.Equal(t, "foo", token.Claims["sub"].(string))
	assert.Equal(t, "", token.Claims["scope"].(string))
}
Пример #9
0
func TestValidAccessToken(t *testing.T) {
	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     "http://localhost:3000/ab",
		LoginProvider:   "xtrac://localhost:9000",
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("RetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	privateKey, publicKey, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(publicKey, nil)

	token, err := rolltoken.GenerateToken("a-subject", "", returnVal.ClientID, returnVal.ApplicationName, privateKey)
	assert.Nil(t, err)

	resp, err := http.Get(addr + TokenInfoURI + "?access_token=" + token)
	assert.Nil(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)

	body := responseAsString(t, resp)
	var ti tokenInfo

	err = json.Unmarshal([]byte(body), &ti)
	assert.Nil(t, err)
	assert.Equal(t, "1111-2222-3333333-4444444", ti.Audience)

}
Пример #10
0
func TestImplGrantAuthValidateAuthenticateOkAdminScope(t *testing.T) {

	var loginCalled = false
	ls := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		loginCalled = true
		w.WriteHeader(http.StatusOK)
	}))
	defer ls.Close()

	//TODO - use a second callback where we serve up a script to extract the page details sent
	//on deny and post those details to another test server.
	var callbackInvoked = false

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		callbackInvoked = true
		println(r.URL.RawQuery)
	}))
	defer ts.Close()

	core, coreConfig := NewTestCore()
	ln, addr := TestServer(t, core)
	defer ln.Close()

	lsURL, _ := url.Parse(ls.URL)

	returnVal := roll.Application{
		DeveloperEmail:  "*****@*****.**",
		ClientID:        "1111-2222-3333333-4444444",
		ApplicationName: "fight club",
		ClientSecret:    "not for browser clients",
		RedirectURI:     ts.URL + "/foo",
		LoginProvider:   "xtrac://" + lsURL.Host,
	}

	appRepoMock := coreConfig.ApplicationRepo.(*mocks.ApplicationRepo)
	appRepoMock.On("SystemRetrieveApplication", "1111-2222-3333333-4444444").Return(&returnVal, nil)

	privateKey, pk, err := secrets.GenerateKeyPair()
	assert.Nil(t, err)

	secretsMock := coreConfig.SecretsRepo.(*mocks.SecretsRepo)
	secretsMock.On("RetrievePrivateKeyForApp", "1111-2222-3333333-4444444").Return(privateKey, nil)
	secretsMock.On("RetrievePublicKeyForApp", "1111-2222-3333333-4444444").Return(pk, nil)

	adminRepoMock := coreConfig.AdminRepo.(*mocks.AdminRepo)
	adminRepoMock.On("IsAdmin", "x").Return(true, nil)

	client := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			fmt.Println(req.URL.Fragment)
			m, _ := url.ParseQuery(req.URL.Fragment)

			accessToken := m.Get("access_token")
			token, err := jwt.Parse(accessToken, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
			assert.Nil(t, err)
			scope, ok := token.Claims["scope"].(string)
			assert.True(t, ok)
			assert.Equal(t, "admin", scope)

			assert.Equal(t, "x", token.Claims["sub"].(string))
			assert.Equal(t, "1111-2222-3333333-4444444", token.Claims["aud"].(string))

			assert.Equal(t, "Bearer", m.Get("token_type"))

			return nil
		},
	}

	_, err = client.PostForm(addr+"/oauth2/validate",
		url.Values{"username": {"x"},
			"password":      {"y"},
			"authorize":     {"allow"},
			"response_type": {"token"},
			"scope":         {"admin"},
			"client_id":     {"1111-2222-3333333-4444444"}})
	assert.Nil(t, err)
	assert.True(t, callbackInvoked)
	assert.True(t, loginCalled)
}
Пример #11
0
func handleApplicationPost(core *roll.Core, w http.ResponseWriter, r *http.Request) {
	var app roll.Application
	if err := parseRequest(r, &app); err != nil {
		respondError(w, http.StatusBadRequest, err)
		return
	}

	//Assign a client ID
	id, err := core.GenerateID()
	if err != nil {
		respondError(w, http.StatusInternalServerError, err)
		return
	}

	app.ClientID = id

	//Validate the content
	if err := app.Validate(); err != nil {
		respondError(w, http.StatusBadRequest, err)
		return
	}

	//Extract the subject from the request header based on security mode
	subject, _, err := subjectAndAdminScopeFromRequestCtx(r)
	if err != nil {
		log.Print("Error extracting subject:", err.Error())
		respondError(w, http.StatusInternalServerError, nil)
		return
	}

	app.DeveloperID = subject

	//Store the application definition
	log.Info("storing app def: ", app)
	err = core.CreateApplication(&app)
	if err != nil {
		log.Info("Error storing app def: ", err.Error())
		switch err.(type) {
		case *repos.DuplicateAppdefError:
			respondError(w, http.StatusConflict, err)
		default:
			respondError(w, http.StatusInternalServerError, err)
		}

		return
	}

	//Generate a private/public key pair
	log.Info("Generate key pair")
	private, public, err := secrets.GenerateKeyPair()
	if err != nil {
		respondError(w, http.StatusBadRequest, err)
		return
	}

	//Store keys in secrets vault
	log.Info("store key pair in vault")
	err = core.StoreKeysForApp(id, private, public)
	if err != nil {
		respondError(w, http.StatusInternalServerError, err)
		return
	}

	//Return the client id
	log.Info("return client id: ", id)
	clientID := ApplicationCreatedResponse{ClientID: id}

	respondOk(w, clientID)

}