Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSO authentication #10

Merged
merged 22 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8de1ab8
Update modules.
lehouque-atos Jun 29, 2023
1e61a09
Add user info and support for user session.
lehouque-atos Jun 29, 2023
0f02b3f
Add oauth2 config.
lehouque-atos Jun 29, 2023
c40be64
Add login and logout endpoints.
lehouque-atos Jun 29, 2023
6494761
Update server and routes.
lehouque-atos Jul 20, 2023
a3e0cba
Replace hard-coded secrets by randomly-generated values.
lehouque-atos Jul 20, 2023
0f4a182
Move harcoded config to config file.
lehouque-atos Jul 20, 2023
369fe5a
Moved UserInfo type to store package, to avoid circular refs.
lehouque-atos Aug 17, 2023
90c1245
Corrected workflows trigger header.
lehouque-atos Aug 17, 2023
0592aa0
Add Base64-encoded random string.
lehouque-atos Nov 10, 2023
17b5bbd
Added saved user session tc autologin file.
lehouque-atos Nov 10, 2023
1957a8f
Added access token to command line client.
lehouque-atos Nov 20, 2023
7e13c50
Updated user session.
lehouque-atos Nov 23, 2023
6e44ca8
Implemented SSO authentication.
lehouque-atos Nov 23, 2023
9cdf41e
Added SSO authentication doc.
lehouque-atos Nov 23, 2023
547f886
Merge branch 'main' into unity-sso
lehouque-atos Nov 23, 2023
9402b3a
Added templates for config files,
lehouque-atos Nov 24, 2023
9451057
Added user ID as identifier.
lehouque-atos Dec 1, 2023
ffa17a2
Removed username from context.
lehouque-atos Dec 1, 2023
3fce59a
Added SSO user ID to context.
lehouque-atos Dec 8, 2023
1e02c33
Updated doc on authentication/authorization via SSO.
lehouque-atos Dec 15, 2023
9c5cf8f
Updated doc on authentication/authorization via SSO.
lehouque-atos Dec 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading