Enable Split Cookies (#318)
This commit is contained in:
1 parent
a4c20164f3
commit
0aba6db720
11 files changed
+174
-49
No files matched your search
@@ -25,12 +25,6 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
HeaderAuthMethod = "Authorization"
|
||||
HttpOnlyCookieName = "wt-http-token-cookie"
|
||||
JsVisibleCookieName = "wt-js-token-cookie"
|
||||
)
|
||||
|
||||
type TokenFormat int
|
||||
|
||||
const (
|
||||
@@ -554,10 +548,10 @@ func GetTokenFromRequest(logger hclog.Logger, kmsCache *kms.Kms, req *http.Reque
|
||||
if receivedTokenType != AuthTokenTypeBearer {
|
||||
var httpCookiePayload string
|
||||
var jsCookiePayload string
|
||||
if hc, err := req.Cookie(HttpOnlyCookieName); err == nil {
|
||||
if hc, err := req.Cookie(handlers.HttpOnlyCookieName); err == nil {
|
||||
httpCookiePayload = hc.Value
|
||||
}
|
||||
if jc, err := req.Cookie(JsVisibleCookieName); err == nil {
|
||||
if jc, err := req.Cookie(handlers.JsVisibleCookieName); err == nil {
|
||||
jsCookiePayload = jc.Value
|
||||
}
|
||||
if httpCookiePayload != "" && jsCookiePayload != "" {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/servers"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/types/action"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
@@ -317,8 +318,8 @@ func TestAuthTokenAuthenticator(t *testing.T) {
|
||||
{
|
||||
name: "Split cookie token",
|
||||
cookies: []http.Cookie{
|
||||
{Name: HttpOnlyCookieName, Value: httpCookieVal},
|
||||
{Name: JsVisibleCookieName, Value: jsCookieVal},
|
||||
{Name: handlers.HttpOnlyCookieName, Value: httpCookieVal},
|
||||
{Name: handlers.JsVisibleCookieName, Value: jsCookieVal},
|
||||
},
|
||||
userId: at.GetIamUserId(),
|
||||
tokenFormat: AuthTokenTypeSplitCookie,
|
||||
@@ -326,14 +327,14 @@ func TestAuthTokenAuthenticator(t *testing.T) {
|
||||
{
|
||||
name: "Split cookie token only http cookie",
|
||||
cookies: []http.Cookie{
|
||||
{Name: HttpOnlyCookieName, Value: httpCookieVal},
|
||||
{Name: handlers.HttpOnlyCookieName, Value: httpCookieVal},
|
||||
},
|
||||
tokenFormat: AuthTokenTypeUnknown,
|
||||
},
|
||||
{
|
||||
name: "Split cookie token only js cookie",
|
||||
cookies: []http.Cookie{
|
||||
{Name: JsVisibleCookieName, Value: jsCookieVal},
|
||||
{Name: handlers.JsVisibleCookieName, Value: jsCookieVal},
|
||||
},
|
||||
tokenFormat: AuthTokenTypeUnknown,
|
||||
},
|
||||
@@ -341,8 +342,8 @@ func TestAuthTokenAuthenticator(t *testing.T) {
|
||||
name: "Cookie and auth header",
|
||||
headers: map[string]string{"Authorization": fmt.Sprintf("Bearer %s", tokValue)},
|
||||
cookies: []http.Cookie{
|
||||
{Name: HttpOnlyCookieName, Value: httpCookieVal},
|
||||
{Name: JsVisibleCookieName, Value: jsCookieVal},
|
||||
{Name: handlers.HttpOnlyCookieName, Value: httpCookieVal},
|
||||
{Name: handlers.JsVisibleCookieName, Value: jsCookieVal},
|
||||
},
|
||||
userId: at.GetIamUserId(),
|
||||
tokenFormat: AuthTokenTypeBearer,
|
||||
|
||||
@@ -2814,7 +2814,7 @@
|
||||
},
|
||||
"token_type": {
|
||||
"type": "string",
|
||||
"description": "This can be \"cookie\" or \"token\". If not provided, \"token\" will be used. For now only type \"token\" is returned."
|
||||
"description": "This can be \"cookie\" or \"token\". If not provided, \"token\" will be used."
|
||||
},
|
||||
"credentials": {
|
||||
"type": "object",
|
||||
@@ -2827,6 +2827,10 @@
|
||||
"properties": {
|
||||
"item": {
|
||||
"$ref": "#/definitions/controller.api.resources.authtokens.v1.AuthToken"
|
||||
},
|
||||
"token_type": {
|
||||
"type": "string",
|
||||
"description": "This can be \"cookie\" or \"token\". If not present, \"token\" should be assumed."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -98,7 +98,7 @@ type AuthenticateRequest struct {
|
||||
// The id to the authmethod in the system being used for authentication. The auth method must be in the scope
|
||||
// being logged in to.
|
||||
AuthMethodId string `protobuf:"bytes,1,opt,name=auth_method_id,json=authMethodId,proto3" json:"auth_method_id,omitempty"`
|
||||
// This can be "cookie" or "token". If not provided, "token" will be used. For now only type "token" is returned.
|
||||
// This can be "cookie" or "token". If not provided, "token" will be used.
|
||||
TokenType string `protobuf:"bytes,2,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
|
||||
// credentials are the different possible credential names depending on what type of auth method is used.
|
||||
// For password auth method: should include only "name" and "password".
|
||||
@@ -164,6 +164,8 @@ type AuthenticateResponse struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Item *authtokens.AuthToken `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
// This can be "cookie" or "token". If not present, "token" should be assumed.
|
||||
TokenType string `protobuf:"bytes,2,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AuthenticateResponse) Reset() {
|
||||
@@ -205,6 +207,13 @@ func (x *AuthenticateResponse) GetItem() *authtokens.AuthToken {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AuthenticateResponse) GetTokenType() string {
|
||||
if x != nil {
|
||||
return x.TokenType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DeauthenticateRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -314,39 +323,41 @@ var file_controller_api_services_v1_authenticate_service_proto_rawDesc = []byte{
|
||||
0x74, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74,
|
||||
0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c,
|
||||
0x73, 0x22, 0x5d, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x73, 0x22, 0x7c, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x41, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x61,
|
||||
0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x32, 0xa0, 0x02, 0x0a, 0x15, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x86, 0x02,
|
||||
0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x2f,
|
||||
0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22,
|
||||
0x17, 0x0a, 0x15, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x61, 0x75,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x32, 0xa0, 0x02, 0x0a, 0x15, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x86, 0x02, 0x0a,
|
||||
0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74,
|
||||
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x92, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x42, 0x22, 0x37, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65,
|
||||
0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68,
|
||||
0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||
0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x47, 0x12,
|
||||
0x45, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20,
|
||||
0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||
0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61, 0x6e,
|
||||
0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f,
|
||||
0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x92, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x42, 0x22, 0x37, 0x2f, 0x76, 0x31, 0x2f, 0x73,
|
||||
0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74,
|
||||
0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f,
|
||||
0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x47, 0x12, 0x45,
|
||||
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x75,
|
||||
0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x20,
|
||||
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
|
||||
0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61,
|
||||
0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -48,7 +48,7 @@ message AuthenticateRequest {
|
||||
// The id to the authmethod in the system being used for authentication. The auth method must be in the scope
|
||||
// being logged in to.
|
||||
string auth_method_id = 1;
|
||||
// This can be "cookie" or "token". If not provided, "token" will be used. For now only type "token" is returned.
|
||||
// This can be "cookie" or "token". If not provided, "token" will be used.
|
||||
string token_type = 2;
|
||||
|
||||
// credentials are the different possible credential names depending on what type of auth method is used.
|
||||
@@ -58,6 +58,8 @@ message AuthenticateRequest {
|
||||
|
||||
message AuthenticateResponse {
|
||||
resources.authtokens.v1.AuthToken item = 1;
|
||||
// This can be "cookie" or "token". If not present, "token" should be assumed.
|
||||
string token_type = 2;
|
||||
}
|
||||
|
||||
message DeauthenticateRequest {}
|
||||
|
||||
@@ -77,6 +77,7 @@ func handleGrpcGateway(c *Controller, props HandlerProperties) (http.Handler, er
|
||||
},
|
||||
}),
|
||||
runtime.WithErrorHandler(handlers.ErrorHandler(c.logger)),
|
||||
runtime.WithForwardResponseOption(handlers.OutgoingIntercepter),
|
||||
)
|
||||
hcs, err := host_catalogs.NewService(c.StaticHostRepoFn)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -8,6 +9,7 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -21,12 +23,23 @@ func TestAuthenticationHandler(t *testing.T) {
|
||||
})
|
||||
defer c.Shutdown()
|
||||
|
||||
resp, err := http.Post(fmt.Sprintf("%s/v1/scopes/%s/auth-methods/ampw_1234567890:authenticate", c.ApiAddrs()[0], scope.Global.String()), "application/json",
|
||||
strings.NewReader(`{"token_type": null, "credentials": {"login_name":"admin", "password": "password123"}}`))
|
||||
request := map[string]interface{}{
|
||||
"credentials": map[string]interface{}{
|
||||
"login_name": "admin",
|
||||
"password": "password123",
|
||||
},
|
||||
}
|
||||
// No token_type defined means "token" type
|
||||
b, err := json.Marshal(request)
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := http.Post(fmt.Sprintf("%s/v1/scopes/%s/auth-methods/ampw_1234567890:authenticate", c.ApiAddrs()[0],
|
||||
scope.Global.String()), "application/json", bytes.NewReader(b))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode, "Got response: %v", resp)
|
||||
|
||||
b, err := ioutil.ReadAll(resp.Body)
|
||||
b, err = ioutil.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
body := make(map[string]interface{})
|
||||
require.NoError(t, json.Unmarshal(b, &body))
|
||||
@@ -37,6 +50,41 @@ func TestAuthenticationHandler(t *testing.T) {
|
||||
assert.NotEmpty(t, pubId)
|
||||
assert.NotEmpty(t, tok)
|
||||
assert.Truef(t, strings.HasPrefix(tok, pubId), "Token: %q, Id: %q", tok, pubId)
|
||||
|
||||
// Set the token type to cookie and make sure the body does not contain the token anymore.
|
||||
request["token_type"] = "cookie"
|
||||
b, err = json.Marshal(request)
|
||||
resp, err = http.Post(fmt.Sprintf("%s/v1/scopes/%s/auth-methods/ampw_1234567890:authenticate", c.ApiAddrs()[0],
|
||||
scope.Global.String()), "application/json", bytes.NewReader(b))
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode, "Got response: %v", resp)
|
||||
|
||||
b, err = ioutil.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
body = make(map[string]interface{})
|
||||
require.NoError(t, json.Unmarshal(b, &body))
|
||||
|
||||
require.Contains(t, body, "id")
|
||||
require.Contains(t, body, "auth_method_id")
|
||||
require.Contains(t, body, "user_id")
|
||||
require.NotContains(t, body, "token")
|
||||
|
||||
cookies := make(map[string]*http.Cookie)
|
||||
for _, c := range resp.Cookies() {
|
||||
cookies[c.Name] = c
|
||||
}
|
||||
require.Contains(t, cookies, handlers.HttpOnlyCookieName)
|
||||
require.Contains(t, cookies, handlers.JsVisibleCookieName)
|
||||
assert.NotEmpty(t, cookies[handlers.HttpOnlyCookieName].Value)
|
||||
assert.NotEmpty(t, cookies[handlers.JsVisibleCookieName].Value)
|
||||
assert.True(t, cookies[handlers.HttpOnlyCookieName].HttpOnly)
|
||||
assert.False(t, cookies[handlers.JsVisibleCookieName].HttpOnly)
|
||||
tok = cookies[handlers.JsVisibleCookieName].Value
|
||||
|
||||
pubId = body["id"].(string)
|
||||
assert.NotEmpty(t, pubId)
|
||||
assert.Truef(t, strings.HasPrefix(tok, pubId), "Token: %q, Id: %q", tok, pubId)
|
||||
}
|
||||
|
||||
func TestHandleImplementedPaths(t *testing.T) {
|
||||
|
||||
@@ -70,7 +70,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pbs.AuthenticateResponse{Item: tok}, nil
|
||||
return &pbs.AuthenticateResponse{Item: tok, TokenType: req.GetTokenType()}, nil
|
||||
}
|
||||
|
||||
// Deauthenticate implements the interface pbs.AuthenticationServiceServer.
|
||||
@@ -171,7 +171,7 @@ func validateAuthenticateRequest(req *pbs.AuthenticateRequest) error {
|
||||
}
|
||||
// TODO: Update this when we enable split cookie token types.
|
||||
tType := strings.ToLower(strings.TrimSpace(req.GetTokenType()))
|
||||
if tType != "" && tType != "token" {
|
||||
if tType != "" && tType != "token" && tType != "cookie" {
|
||||
badFields["token_type"] = "The only accepted type is 'token'."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
|
||||
@@ -23,7 +23,7 @@ var (
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
if maskManager, err = handlers.NewMaskManager(&pb.HostSet{}, &store.HostSet{}); err != nil {
|
||||
if maskManager, err = handlers.NewMaskManager(&store.HostSet{}, &pb.HostSet{}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
HttpOnlyCookieName = "wt-http-token-cookie"
|
||||
JsVisibleCookieName = "wt-js-token-cookie"
|
||||
)
|
||||
|
||||
func OutgoingInterceptor(ctx context.Context, w http.ResponseWriter, m proto.Message) error {
|
||||
m = m.ProtoReflect().Interface()
|
||||
switch m := m.(type) {
|
||||
case *pbs.AuthenticateResponse:
|
||||
if strings.EqualFold(m.GetTokenType(), "cookie") {
|
||||
tok := m.GetItem().GetToken()
|
||||
m.GetItem().Token = ""
|
||||
half := len(tok) / 2
|
||||
jsTok := http.Cookie{
|
||||
Name: JsVisibleCookieName,
|
||||
Value: tok[:half],
|
||||
}
|
||||
httpTok := http.Cookie{
|
||||
Name: HttpOnlyCookieName,
|
||||
Value: tok[half:],
|
||||
HttpOnly: true,
|
||||
}
|
||||
http.SetCookie(w, &jsTok)
|
||||
http.SetCookie(w, &httpTok)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
pb "github.com/hashicorp/boundary/internal/gen/controller/api/resources/authtokens"
|
||||
pbs "github.com/hashicorp/boundary/internal/gen/controller/api/services"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOutgoingSplitCookie(t *testing.T) {
|
||||
rec := httptest.NewRecorder()
|
||||
OutgoingIntercepter(context.Background(), rec, &pbs.AuthenticateResponse{
|
||||
TokenType: "cookie",
|
||||
Item: &pb.AuthToken{Token: "t_abc_1234567890"},
|
||||
})
|
||||
assert.ElementsMatch(t, rec.Result().Cookies(), []*http.Cookie{
|
||||
{Name: HttpOnlyCookieName, Value: "34567890", HttpOnly: true, Raw: "wt-http-token-cookie=34567890; HttpOnly"},
|
||||
{Name: JsVisibleCookieName, Value: "t_abc_12", Raw: "wt-js-token-cookie=t_abc_12"},
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user