-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy pathheart_auth.go
63 lines (58 loc) · 2 KB
/
heart_auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package auth
import (
"fmt"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
// HEARTScopesHandler middleware provides authorization checking aginst the
// scopes described in the Health Relationship Trust Profile for Fast Healthcare
// Interoperability Resources (FHIR) OAuth 2.0 Scopes
// http://openid.bitbucket.org/HEART/openid-heart-fhir-oauth2.html and the
// SMART App Authorization Guide
// http://docs.smarthealthit.org/authorization/
//
// The assumption is that gin handlers run before this one will take care of
// handling the OAuth 2.0 token introspection or OpenID Connect authentication.
// This handler looks at the scopes provided in the gin.Context to see if they
// are appropriate for accessing the resource.
func HEARTScopesHandler(resourceName string) gin.HandlerFunc {
allResourcesAllScope := "user/*.*"
allResourcesReadScope := "user/*.read"
allResourcesWriteScope := "user/*.write"
readScope := fmt.Sprintf("user/%s.read", resourceName)
writeScope := fmt.Sprintf("user/%s.write", resourceName)
allScope := fmt.Sprintf("user/%s.*", resourceName)
return func(c *gin.Context) {
_, exists := c.Get("UserInfo")
if exists {
// This is an OIDC authenticated request. Let it pass through.
return
}
if c.Request.Method == "GET" {
if !includesAnyScope(c, allResourcesAllScope, allResourcesReadScope, readScope, allScope) {
c.String(http.StatusForbidden, "You do not have permission to view this resource")
c.Abort()
return
}
} else {
if !includesAnyScope(c, allResourcesAllScope, allResourcesWriteScope, writeScope, allScope) {
c.String(http.StatusForbidden, "You do not have permission to modify this resource")
c.Abort()
return
}
}
}
}
func includesAnyScope(c *gin.Context, scopes ...string) bool {
grantedScopes, exists := c.Get("scopes")
if exists {
allGrantedScopes := strings.Join(grantedScopes.([]string), " ")
for _, neededScope := range scopes {
if strings.Contains(allGrantedScopes, neededScope) {
return true
}
}
}
return false
}