Skip to content

Commit

Permalink
added registration,authentication and authorization
Browse files Browse the repository at this point in the history
Signed-off-by: guacamole <[email protected]>
  • Loading branch information
guacamole committed Jun 27, 2021
1 parent 59fbadd commit b2dea61
Show file tree
Hide file tree
Showing 17 changed files with 234 additions and 108 deletions.
3 changes: 2 additions & 1 deletion auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
type Authentication interface {
SignUp(ctx echo.Context) error
SignIn(ctx echo.Context) error
BasicAuth(username, password string) (map[string]interface{}, error)
}

type auth struct {
Expand All @@ -19,7 +20,7 @@ type auth struct {
func New(s cache.Store, c *config.RegistryConfig) Authentication {
a := &auth{
store: s,
c: c,
c: c,
}

return a
Expand Down
1 change: 0 additions & 1 deletion auth/bcrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ func (a *auth) verifyPassword(hashedPassword, currPassword string) bool {

return err == nil
}

72 changes: 63 additions & 9 deletions auth/jwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,75 @@ import (
"time"
)

func (a *auth) newToken(u User) (string,error) {
token := jwt.New(jwt.SigningMethodHS256)
type Claims struct {
jwt.StandardClaims
Access AccessList
}

// Set claims
claims := token.Claims.(jwt.MapClaims)
claims["username"] = u.Username
claims["push"] = true
claims["exp"] = time.Now().Add(time.Hour * 24*14).Unix()
func (a *auth) newToken(u User, tokenLife int64) (string, error) {
//for now we're sending same name for sub and name.
//TODO when repositories need collaborators
claims := a.createClaims(u.Username, u.Username, tokenLife)
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

// Generate encoded token and send it as response.
fmt.Printf("secret %s:",a.c.SigningSecret)
t, err := token.SignedString([]byte(a.c.SigningSecret))
if err != nil {
return "",err
return "", err

}

return t, nil
}

func (a *auth) createClaims(sub, name string, tokenLife int64) Claims {
claims := Claims{
StandardClaims: jwt.StandardClaims{
Audience: "openregistry.dev",
ExpiresAt: tokenLife,
Id: "",
IssuedAt: time.Now().Unix(),
Issuer: "openregistry.dev",
NotBefore: time.Now().Unix(),
Subject: sub,
},
Access: AccessList{
{
Type: "repository",
Name: fmt.Sprintf("%s/*", name),
Actions: []string{"push", "pull"},
},
},
}

return claims
}

type AccessList []struct {
Type string `json:"type"`
Name string `json:"name"`
Actions []string `json:"actions"`
}

/*
claims format
{
"iss": "auth.docker.com",
"sub": "jlhawn",
"aud": "registry.docker.com",
"exp": 1415387315,
"nbf": 1415387015,
"iat": 1415387015,
"jti": "tYJCO1c6cnyy7kAn0c7rKPgbV1H1bFws",
"access": [
{
"type": "repository",
"name": "samalba/my-app",
"actions": [
"pull",
"push"
]
}
]
}
*/
45 changes: 24 additions & 21 deletions auth/signin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,59 +5,62 @@ import (
"fmt"
"github.com/labstack/echo/v4"
"net/http"
"time"
)

func (a *auth) SignIn(ctx echo.Context) error {
var user User

if err := json.NewDecoder(ctx.Request().Body).Decode(&user); err!= nil {
return ctx.JSON(http.StatusBadRequest,echo.Map{
if err := json.NewDecoder(ctx.Request().Body).Decode(&user); err != nil {
return ctx.JSON(http.StatusBadRequest, echo.Map{
"error": err.Error(),
})
}
if user.Email == "" || user.Password == ""{
return ctx.JSON(http.StatusBadRequest,echo.Map{
if user.Email == "" || user.Password == "" {
return ctx.JSON(http.StatusBadRequest, echo.Map{
"error": "Email/Password cannot be empty",
})
}

if err:= verifyEmail(user.Email); err!= nil {
return ctx.JSON(http.StatusBadRequest,echo.Map{
if err := verifyEmail(user.Email); err != nil {
return ctx.JSON(http.StatusBadRequest, echo.Map{
"error": err.Error(),
})
}

key := fmt.Sprintf("%s/%s",UserNameSpace,user.Email)
bz,err := a.store.Get([]byte(key))
if err!= nil{
return ctx.JSON(http.StatusBadRequest,echo.Map{
key := fmt.Sprintf("%s/%s", UserNameSpace, user.Username)
bz, err := a.store.Get([]byte(key))
if err != nil {
return ctx.JSON(http.StatusBadRequest, echo.Map{
"error": err.Error(),
})
}

var userFromDb User
if err := json.Unmarshal(bz,&userFromDb); err!= nil {
return ctx.JSON(http.StatusInternalServerError,echo.Map{
if err := json.Unmarshal(bz, &userFromDb); err != nil {
return ctx.JSON(http.StatusInternalServerError, echo.Map{
"error": err.Error(),
})
}

if !a.verifyPassword(userFromDb.Password,user.Password) {
return ctx.JSON(http.StatusUnauthorized,echo.Map{
if !a.verifyPassword(userFromDb.Password, user.Password) {
return ctx.JSON(http.StatusUnauthorized, echo.Map{
"error": "invalid password",
})
}

token,err := a.newToken(user)
if err!= nil{
return ctx.JSON(http.StatusInternalServerError,echo.Map{
"error": err.Error(),
tokenLife := time.Now().Add(time.Hour * 24 * 14).Unix()
token, err := a.newToken(user, tokenLife)
if err != nil {
return ctx.JSON(http.StatusInternalServerError, echo.Map{
"error": err.Error(),
})
}

return ctx.JSON(http.StatusOK,echo.Map{
"message": "user authenticated",
"token": token,
return ctx.JSON(http.StatusOK, echo.Map{
"token": token,
"expires_in": tokenLife,
"issued_at": time.Now().Unix(),
})

}
7 changes: 4 additions & 3 deletions auth/signup.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ const UserNameSpace = "users"

func (a *auth) ValidateUser(u User) error {

if err := verifyEmail(u.Email); err!= nil {return err}
if err := verifyEmail(u.Email); err != nil {
return err
}
key := fmt.Sprintf("%s/%s", UserNameSpace, u.Email)
_, err := a.store.Get([]byte(key))
if err == nil {
Expand All @@ -39,7 +41,6 @@ func (a *auth) ValidateUser(u User) error {
}

if bz != nil {

var userList []User
fmt.Printf("%s\n", bz)
if err := json.Unmarshal(bz, &userList); err != nil {
Expand Down Expand Up @@ -169,7 +170,7 @@ func (a *auth) SignUp(ctx echo.Context) error {
u.Password = hpwd
bz, _ = json.Marshal(u)

key := fmt.Sprintf("%s/%s", UserNameSpace, u.Email)
key := fmt.Sprintf("%s/%s", UserNameSpace, u.Username)
if err := a.store.Set([]byte(key), bz); err != nil {
return ctx.JSON(http.StatusInternalServerError, echo.Map{
"error": err.Error(),
Expand Down
41 changes: 41 additions & 0 deletions auth/validate_user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package auth

import (
"encoding/json"
"fmt"
"github.com/labstack/echo/v4"
"time"
)

func (a *auth) BasicAuth(username, password string) (map[string]interface{}, error) {
if username == "" || password == "" {
return nil, fmt.Errorf("Email/Password cannot be empty")
}

key := fmt.Sprintf("%s/%s", UserNameSpace, username)
bz, err := a.store.Get([]byte(key))
if err != nil {
return nil, err
}

var userFromDb User
if err := json.Unmarshal(bz, &userFromDb); err != nil {
return nil, err
}

if !a.verifyPassword(userFromDb.Password, password) {
return nil, fmt.Errorf("invalid password")
}

tokenLife := time.Now().Add(time.Hour * 24 * 14).Unix()
token, err := a.newToken(User{Username: username}, tokenLife)
if err != nil {
return nil, err
}

return echo.Map{
"token": token,
"expires_in": tokenLife,
"issued_at": time.Now().Unix(),
}, nil
}
9 changes: 4 additions & 5 deletions docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ func newConfigFromEnv(c *config.RegistryConfig) *Client {
}
}


func (c *Client) HasImage(imageID string) (bool, error) {
args := filters.NewArgs()
args.Add("references", StripImageTagHost(imageID))
Expand Down Expand Up @@ -94,10 +93,10 @@ func (c *Client) PullImage(imageID string) error {

func (c *Client) PushImage(imageID string) error {
r, err := c.docker.ImagePush(context.Background(), imageID, types.ImagePushOptions{
All: false,
RegistryAuth: "anything-will-work",
PrivilegeFunc: func() (string, error) {return "", nil},
Platform: "",
All: false,
RegistryAuth: "anything-will-work",
PrivilegeFunc: func() (string, error) { return "", nil },
Platform: "",
})
if err != nil {
return err
Expand Down
Loading

0 comments on commit b2dea61

Please sign in to comment.