예제 #1
0
파일: token.go 프로젝트: xtraclabs/roll
func subjectFromBearerToken(core *roll.Core, r *http.Request) (string, error) {
	//Check for header presence
	authzHeader := r.Header.Get("Authorization")
	if authzHeader == "" {
		return "", errors.New("Authorization header missing from request")
	}

	//Header format should be Bearer token
	parts := strings.SplitAfter(authzHeader, "Bearer")
	if len(parts) != 2 {
		return "", errors.New("Unexpected authorization header format - expecting bearer token")
	}

	//Parse the token
	bearerToken := strings.TrimSpace(parts[1])
	token, err := jwt.Parse(bearerToken, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
	if err != nil {
		return "", err
	}

	//Grab the subject from the claims
	subject, ok := token.Claims["sub"].(string)
	if !ok {
		return "", errors.New("problem with subject claim")
	}

	//Is the subject something other than an empty string?
	if subject == "" {
		return "", errors.New("empty subject claim")
	}

	return subject, nil
}
예제 #2
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)
}
예제 #3
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))
}
예제 #4
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)

}
예제 #5
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))
}
예제 #6
0
파일: token.go 프로젝트: xtraclabs/roll
func validateAndReturnCodeToken(secretsRepo secrets.SecretsRepo, ctx *authCodeContext, clientID string) (*jwt.Token, error) {
	token, err := jwt.Parse(ctx.authCode, rolltoken.GenerateKeyExtractionFunction(secretsRepo))
	if err != nil {
		return nil, err
	}

	//Make sure the token is valid
	if !token.Valid {
		log.Info("Invalid token presented to service: ", token)
		return nil, errors.New("Invalid authorization code")
	}

	//make sure the client_id used to validate the token matches the token aud claim
	if clientID != token.Claims["aud"] {
		return nil, errors.New("Token not associated with client id")
	}

	return token, nil
}
예제 #7
0
파일: tokeninfo.go 프로젝트: xtraclabs/roll
func handleTokenInfoGet(core *roll.Core, w http.ResponseWriter, r *http.Request) {
	//Grab the token
	tokenString := r.FormValue("access_token")
	if tokenString == "" {
		log.Info("missing access token")
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	//Parse and validate the token
	token, err := jwt.Parse(tokenString, rolltoken.GenerateKeyExtractionFunction(core.SecretsRepo))
	if err != nil {
		log.Info(err.Error())
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	//Panic is there's no aud claim
	audience := token.Claims["aud"]
	if audience == "" {
		panic(errors.New("No aud claim in token"))
	}

	//Return the token info
	tokenInfo := &tokenInfo{
		Audience: audience.(string),
	}

	bytes, err := json.Marshal(&tokenInfo)
	if err != nil {
		respondError(w, http.StatusInternalServerError, err)
		return
	}

	w.Write(bytes)
}
예제 #8
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)
}