From 84ba530dff9784260c88886648b7ab95c2ef5357 Mon Sep 17 00:00:00 2001 From: Dick Appel Date: Tue, 23 Nov 2021 09:16:39 +0100 Subject: [PATCH 1/2] feat: added support for personal-access-tokens - added a new PATAuthTransport type that has a 'Token' attribute to hold your unique PAT - setting the Authorization header with the bearer token in the RoundTrip function. - added test to prove to the token gets passed via the header - bonus: fixed typo in existing test name --- authentication_test.go | 2 +- jira.go | 34 ++++++++++++++++++++++++++++++++++ jira_test.go | 23 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/authentication_test.go b/authentication_test.go index 431a7fdc..9235d080 100644 --- a/authentication_test.go +++ b/authentication_test.go @@ -133,7 +133,7 @@ func TestAuthenticationService_Authenticated_WithBasicAuthButNoUsername(t *testi } } -func TestAithenticationService_GetUserInfo_AccessForbidden_Fail(t *testing.T) { +func TestAuthenticationService_GetUserInfo_AccessForbidden_Fail(t *testing.T) { setup() defer teardown() testMux.HandleFunc("/rest/auth/1/session", func(w http.ResponseWriter, r *http.Request) { diff --git a/jira.go b/jira.go index 66046a45..b628ec67 100644 --- a/jira.go +++ b/jira.go @@ -382,6 +382,40 @@ func (t *BasicAuthTransport) transport() http.RoundTripper { return http.DefaultTransport } +// PATAuthTransport is an http.RoundTripper that authenticates all requests +// using the Personal Access Token specified. +type PATAuthTransport struct { + Token string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. We just add the +// basic auth and return the RoundTripper for this transport type. +func (t *PATAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + req2.Header.Set("Authorization", "Bearer "+t.Token) + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. This is a nice little bit of sugar +// so we can just get the client instead of creating the client in the calling code. +// If it's necessary to send more information on client init, the calling code can +// always skip this and set the transport itself. +func (t *PATAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *PATAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + // CookieAuthTransport is an http.RoundTripper that authenticates all requests // using Jira's cookie-based authentication. // diff --git a/jira_test.go b/jira_test.go index 9f34dd78..3aedbd64 100644 --- a/jira_test.go +++ b/jira_test.go @@ -631,3 +631,26 @@ func TestJWTAuthTransport_HeaderContainsJWT(t *testing.T) { jwtClient, _ := NewClient(jwtTransport.Client(), testServer.URL) jwtClient.Issue.Get("TEST-1", nil) } + +func TestPATAuthTransport_HeaderContainsAuth(t *testing.T) { + setup() + defer teardown() + + token := "shhh, it's a token" + + patTransport := &PATAuthTransport{ + Token: token, + } + + testMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + val := r.Header.Get("Authorization") + expected := "Bearer " + token + if val != expected { + t.Errorf("request does not contain bearer token in the Authorization header.") + } + }) + + client, _ := NewClient(patTransport.Client(), testServer.URL) + client.User.GetSelf() + +} From 3b2368d4cbfccff65fa493ea0a66a94785a80b1e Mon Sep 17 00:00:00 2001 From: Dick Appel Date: Tue, 21 Dec 2021 11:20:21 +0100 Subject: [PATCH 2/2] docs: added comment on Token field and ref to PAT documentation. --- jira.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jira.go b/jira.go index b628ec67..a6e6b2e6 100644 --- a/jira.go +++ b/jira.go @@ -384,7 +384,9 @@ func (t *BasicAuthTransport) transport() http.RoundTripper { // PATAuthTransport is an http.RoundTripper that authenticates all requests // using the Personal Access Token specified. +// See here for more info: https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html type PATAuthTransport struct { + // Token is the key that was provided by Jira when creating the Personal Access Token. Token string // Transport is the underlying HTTP transport to use when making requests.