Skip to content

Commit 0c69695

Browse files
committed
Added authentication helpers
1 parent ac35bf2 commit 0c69695

File tree

2 files changed

+121
-7
lines changed

2 files changed

+121
-7
lines changed

auth.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Ewout Prangsma
21+
//
22+
23+
package main
24+
25+
import (
26+
"fmt"
27+
"io/ioutil"
28+
"strings"
29+
30+
"github.com/spf13/cobra"
31+
32+
service "github.com/arangodb-helper/arangodb/service"
33+
)
34+
35+
var (
36+
cmdAuth = &cobra.Command{
37+
Use: "auth",
38+
Short: "ArangoDB authentication helper commands",
39+
Run: cmdShowUsage,
40+
}
41+
cmdAuthHeader = &cobra.Command{
42+
Use: "header",
43+
Short: "Create a full HTTP Authorization header for accessing an ArangoDB server",
44+
Run: cmdAuthHeaderRun,
45+
}
46+
cmdAuthToken = &cobra.Command{
47+
Use: "token",
48+
Short: "Create a JWT authentication token for accessing an ArangoDB server",
49+
Run: cmdAuthTokenRun,
50+
}
51+
authOptions struct {
52+
jwtSecretFile string
53+
}
54+
)
55+
56+
func init() {
57+
cmdMain.AddCommand(cmdAuth)
58+
cmdAuth.AddCommand(cmdAuthHeader)
59+
cmdAuth.AddCommand(cmdAuthToken)
60+
61+
pf := cmdAuth.PersistentFlags()
62+
pf.StringVar(&authOptions.jwtSecretFile, "auth.jwt-secret", "", "name of a plain text file containing a JWT secret used for server authentication")
63+
}
64+
65+
// mustAuthCreateJWTToken creates a the JWT token based on authentication options.
66+
// On error the process is exited with a non-zero exit code.
67+
func mustAuthCreateJWTToken() string {
68+
authOptions.jwtSecretFile = mustExpand(authOptions.jwtSecretFile)
69+
70+
if authOptions.jwtSecretFile == "" {
71+
log.Fatal().Msg("A JWT secret file is required. Set --auth.jwt-secret option.")
72+
}
73+
content, err := ioutil.ReadFile(authOptions.jwtSecretFile)
74+
if err != nil {
75+
log.Fatal().Err(err).Msgf("Failed to read JWT secret file '%s'", authOptions.jwtSecretFile)
76+
}
77+
jwtSecret := strings.TrimSpace(string(content))
78+
token, err := service.CreateJwtToken(jwtSecret)
79+
if err != nil {
80+
log.Fatal().Err(err).Msg("Failed to create JWT token")
81+
}
82+
return token
83+
}
84+
85+
// cmdAuthHeaderRun prints a JWT authorization header on stdout and exits.
86+
func cmdAuthHeaderRun(cmd *cobra.Command, args []string) {
87+
token := mustAuthCreateJWTToken()
88+
fmt.Printf("%s: %s%s\n", service.AuthorizationHeader, service.BearerPrefix, token)
89+
}
90+
91+
// cmdAuthTokenRun prints a JWT authorization token on stdout and exits.
92+
func cmdAuthTokenRun(cmd *cobra.Command, args []string) {
93+
token := mustAuthCreateJWTToken()
94+
fmt.Println(token)
95+
}

service/authentication.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@ import (
2828
jwt "github.com/dgrijalva/jwt-go"
2929
)
3030

31-
// addJwtHeader calculates a JWT authorization header based on the given secret
32-
// and adds it to the given request.
33-
// If the secret is empty, nothing is done.
34-
func addJwtHeader(req *http.Request, jwtSecret string) error {
31+
const (
32+
AuthorizationHeader = "Authorization"
33+
BearerPrefix = "bearer "
34+
)
35+
36+
// CreateJwtToken calculates a JWT authorization token based on the given secret.
37+
// If the secret is empty, an empty token is returned.
38+
func CreateJwtToken(jwtSecret string) (string, error) {
3539
if jwtSecret == "" {
36-
return nil
40+
return "", nil
3741
}
3842
// Create a new token object, specifying signing method and the claims
3943
// you would like it to contain.
@@ -44,11 +48,26 @@ func addJwtHeader(req *http.Request, jwtSecret string) error {
4448

4549
// Sign and get the complete encoded token as a string using the secret
4650
signedToken, err := token.SignedString([]byte(jwtSecret))
51+
if err != nil {
52+
return "", maskAny(err)
53+
}
54+
55+
return signedToken, nil
56+
}
57+
58+
// addJwtHeader calculates a JWT authorization header based on the given secret
59+
// and adds it to the given request.
60+
// If the secret is empty, nothing is done.
61+
func addJwtHeader(req *http.Request, jwtSecret string) error {
62+
if jwtSecret == "" {
63+
return nil
64+
}
65+
signedToken, err := CreateJwtToken(jwtSecret)
4766
if err != nil {
4867
return maskAny(err)
4968
}
5069

51-
req.Header.Set("Authorization", "bearer "+signedToken)
70+
req.Header.Set(AuthorizationHeader, BearerPrefix+signedToken)
5271
return nil
5372
}
5473

@@ -60,6 +79,6 @@ func addBearerTokenHeader(req *http.Request, bearerToken string) error {
6079
return nil
6180
}
6281

63-
req.Header.Set("Authorization", "bearer "+bearerToken)
82+
req.Header.Set(AuthorizationHeader, BearerPrefix+bearerToken)
6483
return nil
6584
}

0 commit comments

Comments
 (0)