Skip to content

Commit

Permalink
new: added SAML auth (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
primalmotion authored Aug 21, 2019
1 parent 136ab42 commit 90faa51
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 4 deletions.
44 changes: 44 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,50 @@ func (a *Client) IssueFromOIDCStep2(ctx context.Context, code string, state stri
return a.sendRequest(subctx, issueRequest)
}

// IssueFromSAMLStep1 issues a Midgard jwt from a SAML provider. This is performing the first step to
// validate the issue requests and OIDC provider. It will return the OIDC auth endpoint
func (a *Client) IssueFromSAMLStep1(ctx context.Context, namespace string, provider string, redirectURL string) (string, error) {

issueRequest := gaia.NewIssue()
issueRequest.Metadata = map[string]interface{}{
"namespace": namespace,
"SAMLProviderName": provider,
"redirectURL": redirectURL,
}
issueRequest.Realm = gaia.IssueRealmSAML

span, subctx := opentracing.StartSpanFromContext(ctx, "midgardlib.client.issue.saml.step1")
defer span.Finish()

return a.sendRequest(subctx, issueRequest)
}

// IssueFromSAMLStep2 issues a Midgard jwt from a SAML provider. This is performing the second step to
// to exchange the code for a Midgard HWT.
func (a *Client) IssueFromSAMLStep2(ctx context.Context, response string, state string, validity time.Duration, options ...Option) (string, error) {

opts := issueOpts{}
for _, opt := range options {
opt(&opts)
}

issueRequest := gaia.NewIssue()
issueRequest.Metadata = map[string]interface{}{
"SAMLResponse": response,
"relayState": state,
}
issueRequest.Realm = gaia.IssueRealmSAML
issueRequest.Validity = validity.String()
issueRequest.Quota = opts.quota
issueRequest.Opaque = opts.opaque
issueRequest.Audience = opts.audience

span, subctx := opentracing.StartSpanFromContext(ctx, "midgardlib.client.issue.saml.step2")
defer span.Finish()

return a.sendRequest(subctx, issueRequest)
}

// IssueFromAzureIdentityToken issues a Midgard jwt from a signed Azure identity document for the given validity duration.
func (a *Client) IssueFromAzureIdentityToken(ctx context.Context, token string, validity time.Duration, options ...Option) (string, error) {

Expand Down
91 changes: 87 additions & 4 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,47 @@ func TestClient_IssueFromAzureIdentityToken(t *testing.T) {

func TestClient_IssueFromOIDCStep1(t *testing.T) {

Convey("Given I have a client and a fake working server", t, func() {

expectedRequest := gaia.NewIssue()

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(expectedRequest); err != nil {
panic(err)
}

w.Header().Set("Location", "http://laba")
w.WriteHeader(http.StatusFound)

}))
defer ts.Close()

cl := NewClient(ts.URL)

Convey("When I call IssueFromOIDCStep1(", func() {

ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

url, err := cl.IssueFromOIDCStep1(ctx, "aporeto", "okta", "http://ici")

Convey("Then err should be nil", func() {
So(err, ShouldBeNil)
})

Convey("Then the issue request should be correct", func() {
So(expectedRequest.Realm, ShouldEqual, "OIDC")
})

Convey("Then url should be correct", func() {
So(url, ShouldEqual, "http://laba")
})
})
})
}

func TestClient_IssueFromOIDCStep2(t *testing.T) {

Convey("Given I have a client and a fake working server", t, func() {

expectedRequest := gaia.NewIssue()
Expand Down Expand Up @@ -521,7 +562,7 @@ func TestClient_IssueFromOIDCStep1(t *testing.T) {
})
}

func TestClient_IssueFromOIDCStep2(t *testing.T) {
func TestClient_IssueFromSAMLStep1(t *testing.T) {

Convey("Given I have a client and a fake working server", t, func() {

Expand All @@ -540,19 +581,19 @@ func TestClient_IssueFromOIDCStep2(t *testing.T) {

cl := NewClient(ts.URL)

Convey("When I call IssueFromOIDCStep1(", func() {
Convey("When I call IssueFromSAMLStep1(", func() {

ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

url, err := cl.IssueFromOIDCStep1(ctx, "aporeto", "okta", "http://ici")
url, err := cl.IssueFromSAMLStep1(ctx, "aporeto", "okta", "http://ici")

Convey("Then err should be nil", func() {
So(err, ShouldBeNil)
})

Convey("Then the issue request should be correct", func() {
So(expectedRequest.Realm, ShouldEqual, "OIDC")
So(expectedRequest.Realm, ShouldEqual, "SAML")
})

Convey("Then url should be correct", func() {
Expand All @@ -562,6 +603,48 @@ func TestClient_IssueFromOIDCStep2(t *testing.T) {
})
}

func TestClient_IssueFromSAMLStep2(t *testing.T) {

Convey("Given I have a client and a fake working server", t, func() {

expectedRequest := gaia.NewIssue()

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if err := json.NewDecoder(r.Body).Decode(expectedRequest); err != nil {
panic(err)
}

fmt.Fprintln(w, `{"data": "","realm": "saml","token": "token"}`)

}))
defer ts.Close()

cl := NewClient(ts.URL)

Convey("When I call IssueFromSAMLStep2", func() {

ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

token, err := cl.IssueFromSAMLStep2(ctx, "response", "state", 1*time.Minute, OptQuota(1))

Convey("Then err should be nil", func() {
So(err, ShouldBeNil)
})

Convey("Then the issue request should be correct", func() {
So(expectedRequest.Realm, ShouldEqual, "SAML")
So(expectedRequest.Metadata["SAMLResponse"], ShouldEqual, "response")
So(expectedRequest.Metadata["relayState"], ShouldEqual, "state")
})

Convey("Then token should be correct", func() {
So(token, ShouldEqual, "token")
})
})
})
}

func TestClient_IssueFromAWSSecurityToken(t *testing.T) {

Convey("Given I have a fake working server", t, func() {
Expand Down

0 comments on commit 90faa51

Please sign in to comment.