Skip to content

Commit

Permalink
feat: authenticate with authserver
Browse files Browse the repository at this point in the history
  • Loading branch information
robinmuhia committed Jul 18, 2024
1 parent 53eb684 commit 61d9f03
Show file tree
Hide file tree
Showing 9 changed files with 483 additions and 319 deletions.
78 changes: 38 additions & 40 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
# Options for analysis running.
run:
skip-dirs:
- pkg/mycarehub/presentation/graph/
linters:
disable-all: true
enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- asciicheck
- bodyclose
- dogsled
- exhaustive
- exportloopref
- gocognit
- goconst
- gofmt
- goheader
- goimports
- gosec
- misspell
- nakedret
- nestif
- noctx
- rowserrcheck
- sqlclosecheck
- unconvert
- unparam
- whitespace
- gocyclo
- golint
timeout: 10m
concurrency: 4

linters:
disable-all: true
enable:
- unused
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asciicheck
- bodyclose
- dogsled
- exhaustive
- exportloopref
- gocognit
- goconst
- gofmt
- goheader
- goimports
- gosec
- misspell
- nakedret
- nestif
- noctx
- rowserrcheck
- sqlclosecheck
- unconvert
- unparam
- whitespace
- gocyclo
- revive

linters-settings:
staticcheck:
checks: ["all"]
linters-settings:
staticcheck:
checks: ["all"]
87 changes: 27 additions & 60 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"net/url"
"time"

"github.com/mitchellh/mapstructure"
"github.com/savannahghi/authutils"
"github.com/savannahghi/serverutils"
"github.com/sirupsen/logrus"
)
Expand All @@ -26,15 +26,23 @@ var (

// accessTokenTimeout shows the access token expiry time.
// After the access token expires, one is required to obtain a new one
accessTokenTimeout = 30 * time.Minute
accessTokenTimeout = 60 * time.Minute

// refreshTokenTimeout shows the refresh token expiry time
refreshTokenTimeout = 24 * time.Hour
)

// AuthServerImpl defines the methods provided by
// the auth server library
type AuthServerImpl interface {
LoginUser(ctx context.Context, input *authutils.LoginUserPayload) (*authutils.OAUTHResponse, error)
RefreshToken(ctx context.Context, refreshToken string) (*authutils.OAUTHResponse, error)
}

// It is the client used to make API request to sil communications API
type client struct {
client *http.Client
authServer AuthServerImpl
client *http.Client

refreshToken string
refreshTokenTicker *time.Ticker
Expand All @@ -46,11 +54,12 @@ type client struct {
}

// newClient initializes a new SIL comms client instance
func newClient() (*client, error) {
func newClient(authServer AuthServerImpl) (*client, error) {
s := &client{
client: &http.Client{
Timeout: time.Second * 10,
},
authServer: authServer,
accessToken: "",
refreshToken: "",
authFailed: false,
Expand All @@ -68,8 +77,8 @@ func newClient() (*client, error) {
}

// mustNewClient initializes a new SIL comms client instance
func mustNewClient() *client {
client, err := newClient()
func mustNewClient(authServer AuthServerImpl) *client {
client, err := newClient(authServer)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -120,87 +129,46 @@ func (s *client) setRefreshToken(token string) {
}
}

// login uses the provided credentials to login to the SIL communications backend
// login uses the provided credentials to login to the authserver backend
// It obtains the necessary tokens required to make authenticated requests
func (s *client) login() error {
path := "/auth/token/"
payload := struct {
Email string `json:"email"`
Password string `json:"password"`
}{
ctx := context.Background()

loginInput := authutils.LoginUserPayload{
Email: email,
Password: password,
}

response, err := s.MakeRequest(context.Background(), http.MethodPost, path, nil, payload, false)
resp, err := s.authServer.LoginUser(ctx, &loginInput)
if err != nil {
err = fmt.Errorf("failed to make login request: %w", err)
return err
}

if response.StatusCode != http.StatusOK {
err := fmt.Errorf("invalid login response code, got: %d", response.StatusCode)
return err
}

var resp APIResponse
err = json.NewDecoder(response.Body).Decode(&resp)
if err != nil {
err = fmt.Errorf("failed to decode login api response: %w", err)
return err
}

var tokens TokenResponse
err = mapstructure.Decode(resp.Data, &tokens)
if err != nil {
err = fmt.Errorf("failed to decode login data in api response: %w", err)
return err
tokens := TokenResponse{
Access: resp.AccessToken,
Refresh: resp.RefreshToken,
}

s.setRefreshToken(tokens.Refresh)
s.setAccessToken(tokens.Access)

return nil

}

func (s *client) refreshAccessToken() error {
path := "/auth/token/refresh/"
payload := struct {
Refresh string `json:"refresh"`
}{
Refresh: s.refreshToken,
}

response, err := s.MakeRequest(context.Background(), http.MethodPost, path, nil, payload, false)
ctx := context.Background()
resp, err := s.authServer.RefreshToken(ctx, s.refreshToken)
if err != nil {
err = fmt.Errorf("failed to make refresh request: %w", err)
return err
}

if response.StatusCode != http.StatusOK {
err := fmt.Errorf("invalid refresh token response code, got: %d", response.StatusCode)
return err
}

var resp APIResponse
err = json.NewDecoder(response.Body).Decode(&resp)
if err != nil {
err = fmt.Errorf("failed to decode refresh token api response: %w", err)
return err
}

var tokens TokenResponse
err = mapstructure.Decode(resp.Data, &tokens)
if err != nil {
err = fmt.Errorf("failed to decode refresh token data in api response: %w", err)
return err
tokens := TokenResponse{
Access: resp.AccessToken,
}

s.setAccessToken(tokens.Access)

return nil

}

// MakeRequest performs a HTTP request to the provided path and parameters
Expand Down Expand Up @@ -238,7 +206,6 @@ func (s *client) MakeRequest(ctx context.Context, method, path string, queryPara

default:
return nil, fmt.Errorf("s.MakeRequest() unsupported http method: %s", method)

}

request.Header.Set("Accept", "application/json")
Expand Down
Loading

0 comments on commit 61d9f03

Please sign in to comment.