Skip to content

Commit

Permalink
Merge pull request #10 from eflows4hpc/unity-sso
Browse files Browse the repository at this point in the history
SSO authentication
  • Loading branch information
lehouque-atos authored Dec 15, 2023
2 parents b9b89d1 + 9c5cf8f commit 8ca83c4
Show file tree
Hide file tree
Showing 20 changed files with 504 additions and 14 deletions.
1 change: 1 addition & 0 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Configuration struct {
CAFile string `mapstructure:"ca_file"`
CAPath string `mapstructure:"ca_path"`
User string `mapstructure:"user"`
AccessToken string `mapstructure:"access_token"`

HttpClient *http.Client
}
7 changes: 7 additions & 0 deletions api/http_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ func GetClient(cc Configuration) (HTTPClient, error) {
client.basicAuthUserPass = url.UserPassword(parts[0], parts[1])
}

client.accessToken = strings.TrimSpace(cc.AccessToken)

client.workflows = &workflowsService{client: client}
client.executions = &executionsService{client: client}
client.sshKeys = &sshKeysService{client: client}
Expand All @@ -114,6 +116,7 @@ type client struct {
sshKeys SSHKeysService

basicAuthUserPass *url.Userinfo
accessToken string
}

func (c *client) Workflows() WorkflowsService {
Expand All @@ -123,6 +126,7 @@ func (c *client) Workflows() WorkflowsService {
func (c *client) Executions() ExecutionsService {
return c.executions
}

func (c *client) SSHKeys() SSHKeysService {
return c.sshKeys
}
Expand All @@ -133,6 +137,9 @@ func (c *client) NewRequest(ctx context.Context, method, path string, body io.Re
if err != nil {
return nil, errors.Wrap(err, "Cannot create request")
}
if c.accessToken != "" {
req.Header.Add("Authorization", "Bearer "+c.accessToken)
}

req.URL.User = c.basicAuthUserPass
return req, nil
Expand Down
1 change: 0 additions & 1 deletion api/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ func (s *workflowsService) Trigger(ctx context.Context, workflowID string, input
return "", errors.Wrap(err, "failed to create http request")
}
request.Header.Add("Accept", "application/json")
request.Header.Add("Content-Type", "application/json")

response, err := s.client.Do(request)
if err != nil {
Expand Down
7 changes: 6 additions & 1 deletion cmd/waas/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const certFileFlagName = "cert_file"
const caFileFlagName = "ca_file"
const caPathFlagName = "ca_path"
const userFlagName = "user"
const accessTokenFlagName = "access_token"

func init() {
cobra.OnInitialize(initConfig)
Expand All @@ -120,7 +121,7 @@ func init() {

// Global flags
rootCmd.PersistentFlags().StringVarP(&output, "output", "o", DefaultDisplayOutput, "Output format either \"text\" or \"json\".")
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.hpcwaas-api.yaml)")
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.waas)")
rootCmd.PersistentFlags().String(apiURLFlagName, api.DefaultAPIAddress, "The default URL used to connect to the API")
rootCmd.PersistentFlags().Bool(skipTLSVerifyFlagName, false, "Either or not to skip SSL certificates validation")
rootCmd.PersistentFlags().String(caFileFlagName, "", "CA File to use to validate SSL certificates")
Expand All @@ -136,6 +137,7 @@ If the password is not specified, it will be prompted for.
The user name and passwords are split up on the first colon, which makes it impossible to use a colon in the user name.
However, the password can contains colons.
`)
rootCmd.PersistentFlags().StringP(accessTokenFlagName, "t", "", "Access token for authentication")

// Global flags/config binding
viper.BindPFlag(apiURLFlagName, rootCmd.PersistentFlags().Lookup(apiURLFlagName))
Expand All @@ -145,6 +147,7 @@ However, the password can contains colons.
viper.BindPFlag(keyFileFlagName, rootCmd.PersistentFlags().Lookup(keyFileFlagName))
viper.BindPFlag(certFileFlagName, rootCmd.PersistentFlags().Lookup(certFileFlagName))
viper.BindPFlag(userFlagName, rootCmd.PersistentFlags().Lookup(userFlagName))
viper.BindPFlag(accessTokenFlagName, rootCmd.PersistentFlags().Lookup(accessTokenFlagName))

//Environment Variables
viper.SetEnvPrefix("HW") // HW == HpcWaas
Expand All @@ -158,6 +161,7 @@ However, the password can contains colons.
viper.BindEnv(keyFileFlagName)
viper.BindEnv(certFileFlagName)
viper.BindEnv(userFlagName)
viper.BindEnv(accessTokenFlagName)

// Global defaults
viper.SetDefault(apiURLFlagName, api.DefaultAPIAddress)
Expand All @@ -180,6 +184,7 @@ func initConfig() {
// Search config in home directory with name ".waas" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".waas")
viper.SetConfigType("yaml")
}

viper.AutomaticEnv() // read in environment variables that match
Expand Down
41 changes: 40 additions & 1 deletion docs/rest-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,49 @@ The design of workflows themself is out of the scope of this API and is done by

### Authentication / Authorization

It is using the HTTP Basic authentication. It is also in the process of integrating with Unity Single Sign-On service
HPCWaaS handles authentication with the OAuth 2 protocol. Identities are managed by the Unity identity provider. Authentication in HPCWaaS is a two-ste process:

* Step 1: Retrieve an **access token** by visiting the `/auth/login` endpoint in your browser.
* Step 2: Use the token for sending requests to the API.

#### Authenticating with the REST API

For accessing the REST API with a general utility like `curl`, you need to pass the token in the header, e.g.
`curl -H "Authorization: Bearer <access_token>" ...`

#### Authenticating with the CLI utility

For the `waas` CLI utility, you can pass the token in three different places:

* In the WaaS config file with the `access_token` key, e.g.
`access_token: <access_token>`
* In the `HW_ACCESS_TOKEN` environment variable, e.g.
`export HW_ACCESS_TOKEN=<access_token>`
* In the command-line options, e.g.
`waas workflows list -t=<access_token>`
or
`waas workflows list --access_token=<access_token>`

The parameters take precendence in the following order: command-line option > environment variable > config file.

#### Authorization

To make a workflow visible by the `waas` CLI, you need to add the `hpcwaas-workfows` tag to your workflow, in _alien4cloud_. The tag value will be the name of your workflow.
By default, workflows are public. This means that they are displayed when any user uses the `wass workflows list` command. To restrict access to a workflow to a user (or a group of users), you need to add the `hpcwaas-authorized-users` tag to your workflow. The tag value is a list of comma-seperated UUID of the users you want to allow access to your workflow.
Users can get their Unity UUID by logging in at the `/auth/login` endpoint in their browser.

**Important note:** Without the `hpcwaas-workflows` tag, your workflow won't be visible from the `waas` CLI, even if the `hpcwaas-authorized-users` tag is defined. So, to make a workflow visible to a user (or a group of users), both tags need to be present.

### API Endpoints

#### Request authentication token

This API endpoint is to be used in a browser. It allows, after logging in to a Unity server, to retrieve an **access token** that is needed to authenticate when accessing other endpoints. It also displays your Unity UUID, which can be used to restrict the access to your workflow.

##### Endpoint

`/auth/login`

#### List available workflows

This API endpoint provides the workflows that could be triggered by an *end-user*
Expand Down
17 changes: 12 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ require (
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.39
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/term v0.8.0
gotest.tools/v3 v3.1.0
)

Expand All @@ -35,14 +35,19 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/gin-contrib/sessions v0.0.5 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.10.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.5.7 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/gookit/color v1.5.0 // indirect
github.com/gorilla/context v1.1.1 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
github.com/gorilla/sessions v1.2.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.2.0 // indirect
Expand Down Expand Up @@ -87,10 +92,12 @@ require (
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb // indirect
google.golang.org/grpc v1.45.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
Expand Down
23 changes: 23 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE=
github.com/gin-contrib/sessions v0.0.5/go.mod h1:vYAuaUPqie3WUSsft6HUlCjlwwoJQs97miaG2+7neKY=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
Expand Down Expand Up @@ -171,6 +173,8 @@ github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3a
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down Expand Up @@ -222,6 +226,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
Expand Down Expand Up @@ -254,6 +260,12 @@ github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw=
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/goware/urlx v0.3.1 h1:BbvKl8oiXtJAzOzMqAQ0GfIhf96fKeNEZfm9ocNSUBI=
github.com/goware/urlx v0.3.1/go.mod h1:h8uwbJy68o+tQXCGZNa9D73WN8n0r9OBae5bUnLcgjw=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
Expand Down Expand Up @@ -640,6 +652,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand All @@ -657,6 +671,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -738,11 +754,15 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -753,6 +773,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down Expand Up @@ -858,6 +880,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
Expand Down
84 changes: 84 additions & 0 deletions pkg/rest/authorize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package rest

import (
"context"
"encoding/base64"
"fmt"
"net/http"

"github.com/eflows4hpc/hpcwaas-api/api"
"github.com/eflows4hpc/hpcwaas-api/pkg/store"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)

func (s *Server) authorize(gc *gin.Context) {
// Check state
requestState := gc.Request.FormValue("state")
if requestState != s.Config.Auth.State {
writeError(gc, newBadRequestMessage("request state doesn't match session state"))
return
}

// Exchange code
authorizationCode := gc.Request.FormValue("code")
token, err := s.Config.Auth.OAuth2.Exchange(context.Background(), authorizationCode)
if err != nil {
writeError(gc, newInternalServerError(err))
return
}

// Get user info from endpoint
userInfo, err := s.getUserInfo(gc, token.AccessToken)
if err != nil {
writeError(gc, newInternalServerError(err))
return
}

// Start a new session with user info and token
err = s.store.CreateSession(gc, userInfo, token.AccessToken)
if err != nil {
writeError(gc, newInternalServerError(err))
return
}

// Set user ID in context
userAccount := AuthAccount{Username: userInfo.Sub}
gc.Set(gin.AuthUserKey, userAccount)

encodedToken := base64.StdEncoding.EncodeToString([]byte(token.AccessToken))
msg := fmt.Sprintf(` Log in successful
Welcome %s %s
User ID: %s
You can now use HPCWaaS
For using the CLI, please use the following token:
%s
`, userInfo.FirstName, userInfo.Surname, userInfo.Sub, encodedToken)

gc.String(http.StatusOK, msg)
}

func (s *Server) getUserInfo(ctx context.Context, accessToken string) (*store.UserInfo, error) {
var res store.UserInfo
url := s.Config.Auth.UserInfoURL
request, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, errors.Wrap(err, "failed to create http request")
}
request.Header.Set("Authorization", "Bearer "+accessToken)

client := http.Client{}
response, err := client.Do(request)
if err != nil {
return nil, errors.Wrap(err, "failed to send http request to get user info")
}

err = api.ReadResponse(response, &res)
if err != nil {
return nil, err
}

return &res, nil
}
Loading

0 comments on commit 8ca83c4

Please sign in to comment.