Skip to content

Commit

Permalink
Merge pull request #44 from zalando/feature/scope-checks
Browse files Browse the repository at this point in the history
implement AND and OR checks for scopes provided by the given token
  • Loading branch information
szuecs committed Jan 8, 2018
2 parents 790abed + 8e1892b commit 8f27dda
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
3 changes: 2 additions & 1 deletion example/zalando/main.go
Expand Up @@ -50,7 +50,8 @@ func main() {
private.Use(ginoauth2.AuthChain(zalando.OAuth2Endpoint, zalando.UidCheck(USERS), zalando.GroupCheck(TEAMS), zalando.UidCheck(SERVICES)))
privateGroup.Use(ginoauth2.Auth(zalando.GroupCheck(TEAMS), zalando.OAuth2Endpoint))
privateUser.Use(ginoauth2.Auth(zalando.UidCheck(USERS), zalando.OAuth2Endpoint))
privateService.Use(ginoauth2.Auth(zalando.UidCheck(SERVICES), zalando.OAuth2Endpoint))
//privateService.Use(ginoauth2.Auth(zalando.UidCheck(SERVICES), zalando.OAuth2Endpoint))
privateService.Use(ginoauth2.Auth(zalando.ScopeAndCheck("uidcheck", "uid", "bar"), zalando.OAuth2Endpoint))

private.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "Hello from private for groups and users"})
Expand Down
4 changes: 1 addition & 3 deletions ginoauth2.go
Expand Up @@ -260,11 +260,9 @@ func AuthChain(endpoints oauth2.Endpoint, accessCheckFunctions ...AccessCheckFun
return func(ctx *gin.Context) {
t := time.Now()
varianceControl := make(chan bool, 1)
var tokenContainer *TokenContainer

go func() {
ok := false
tokenContainer, ok = getTokenContainer(ctx)
tokenContainer, ok := getTokenContainer(ctx)
if !ok {
// set LOCATION header to auth endpoint such that the user can easily get a new access-token
ctx.Writer.Header().Set("Location", endpoints.AuthURL)
Expand Down
42 changes: 41 additions & 1 deletion zalando/zalando.go
Expand Up @@ -37,7 +37,7 @@ type TeamInfo struct {

// OAuth2Endpoint is similar to the definitions in golang.org/x/oauth2
var OAuth2Endpoint = oauth2.Endpoint{
AuthURL: "https://token.auth.zalando.com/access_token",
AuthURL: "https://identity.zalando.com/oauth2/token",
TokenURL: "https://info.services.auth.zalando.com/oauth2/tokeninfo",
}

Expand Down Expand Up @@ -122,6 +122,46 @@ func UidCheck(at []AccessTuple) func(tc *ginoauth2.TokenContainer, ctx *gin.Cont
}
}

// ScopeCheck does an OR check of scopes given from token of the
// request to all provided scopes. If one of provided scopes is in the
// Scopes of the token it grants access to the resource.
func ScopeCheck(name string, scopes ...string) func(tc *ginoauth2.TokenContainer, ctx *gin.Context) bool {
glog.Infof("ScopeCheck %s configured to grant access for scopes: %v", name, scopes)
configuredScopes := scopes
return func(tc *ginoauth2.TokenContainer, ctx *gin.Context) bool {
scopesFromToken := make([]string, 0)
for _, s := range configuredScopes {
if cur, ok := tc.Scopes[s].(string); ok {
glog.V(2).Infof("Found configured scope %s", cur)
scopesFromToken = append(scopesFromToken, cur)
ctx.Set(s, cur) // set value from token of configured scope to the context, which you can use in your application.
}
}
return len(scopesFromToken) > 0
}
}

// ScopeAndCheck does an AND check of scopes given from token of the
// request to all provided scopes. Only if all of provided scopes are found in the
// Scopes of the token it grants access to the resource.
func ScopeAndCheck(name string, scopes ...string) func(tc *ginoauth2.TokenContainer, ctx *gin.Context) bool {
glog.Infof("ScopeCheck %s configured to grant access only if scopes: %v are present", name, scopes)
configuredScopes := scopes
return func(tc *ginoauth2.TokenContainer, ctx *gin.Context) bool {
scopesFromToken := make([]string, 0)
for _, s := range configuredScopes {
if cur, ok := tc.Scopes[s].(string); ok {
glog.V(2).Infof("Found configured scope %s", cur)
scopesFromToken = append(scopesFromToken, cur)
ctx.Set(s, cur) // set value from token of configured scope to the context, which you can use in your application.
} else {
return false
}
}
return true
}
}

// NoAuthorization sets "team" and "uid" in the context without
// checking if the user/team is authorized.
func NoAuthorization() func(tc *ginoauth2.TokenContainer, ctx *gin.Context) bool {
Expand Down

0 comments on commit 8f27dda

Please sign in to comment.