Skip to content

Instantly share code, notes, and snippets.

@someone1
Created March 23, 2018 17:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save someone1/ec3625f05cd7082897423d42a39cdfc9 to your computer and use it in GitHub Desktop.
Save someone1/ec3625f05cd7082897423d42a39cdfc9 to your computer and use it in GitHub Desktop.
Google Cloud Endpoints authentication with go-swagger generated server
// CloudEndpointsUserInfo represents the data passed by the ESP in Google's Cloud Endpoints Service
type CloudEndpointsUserInfo struct {
Issuer string `json:"issuer"`
ID string `json:"id"`
Email string `json:"email"`
}
// CloudEndPointsWrapper will try to extract the ESP header and add it as a scope - NOT IDEAL
func CloudEndPointsWrapper(name string, authenticate security.ScopedTokenAuthentication) runtime.Authenticator {
const header = "X-Endpoint-API-UserInfo"
defaultAuthenticator := security.BearerAuth(name, authenticate)
return security.ScopedAuthenticator(func(r *security.ScopedAuthRequest) (bool, interface{}, error) {
encodedInfo := r.Request.Header.Get(header)
if encodedInfo == "" {
return false, nil, fmt.Errorf("missing %s header when it is required", header)
}
b, err := base64.StdEncoding.DecodeString(encodedInfo)
if err != nil {
return false, nil, err
}
r.RequiredScopes = append(r.RequiredScopes, string(b))
return defaultAuthenticator.Authenticate(r)
})
}
// GoogleIDTokenAuth will parse the ESP Header and validate the email is an admin email, otherwise it will fail
func GoogleIDTokenAuth(token string, scopes []string) (*models.UserInfo, error) {
if len(scopes) < 1 {
return nil, errors.Unauthenticated("OIDC")
}
endPointsJSONHeader := scopes[len(scopes)-1]
// scopes = scopes[:len(scopes)-1]
oidcUser := &CloudEndpointsUserInfo{}
if err := json.Unmarshal([]byte(endPointsJSONHeader), oidcUser); err != nil {
return nil, errors.Unauthenticated("OIDC")
}
if !isAdminEamil(oidcUser.Email) {
return nil, errors.New(http.StatusForbidden, "not allowed")
}
userInfo := &models.UserInfo{
ID: oidcUser.ID,
Email: strfmt.Email(oidcUser.Email),
Admin: true,
}
return userInfo, nil
}
func main() {
swaggerSpec, err := loads.Analyzed(restapi.SwaggerJSON, "")
if err != nil {
panic(err)
}
api := operations.NewAPI(swaggerSpec)
api.BearerAuthenticator = CloudEndPointsWrapper
api.GoogleIDTokenAuth = GoogleIDTokenAuth
// and so on...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment