// NewBasicAuthHandler handles basic HTTP auth against the provided user resource func NewBasicAuthHandler(users *resource.Resource) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if u, p, ok := r.BasicAuth(); ok { // Lookup the user by its id ctx := r.Context() user, err := users.Get(ctx, u) if user != nil && err == resource.ErrUnauthorized { // Ignore unauthorized errors set by ourselves err = nil } if err != nil { // If user resource storage handler returned an error, respond with an error if err == resource.ErrNotFound { http.Error(w, "Invalid credential", http.StatusForbidden) } else { http.Error(w, err.Error(), http.StatusInternalServerError) } return } if schema.VerifyPassword(user.Payload["password"], []byte(p)) { // Store the auth user into the context for later use r = r.WithContext(NewContextWithUser(ctx, user)) next.ServeHTTP(w, r) return } } // Stop the middleware chain and return a 401 HTTP error w.Header().Set("WWW-Authenticate", `Basic realm="API"`) http.Error(w, "Please provide proper credentials", http.StatusUnauthorized) }) } }
func (m myAuthMiddleware) Handle(ctx context.Context, r *http.Request, next rest.Next) (context.Context, int, http.Header, interface{}) { if u, p, ok := r.BasicAuth(); ok { // Lookup the user by its id lookup := resource.NewLookupWithQuery(schema.Query{ schema.Equal{Field: "id", Value: u}, }) list, err := m.userResource.Find(ctx, lookup, 1, 1) if err != nil { // If user resource storage handler returned an error, stop the middleware chain return ctx, 0, nil, err } if len(list.Items) == 1 { user := list.Items[0] if schema.VerifyPassword(user.Payload["password"], []byte(p)) { // Get the current route from the context route, ok := rest.RouteFromContext(ctx) if ok { // If the current resource is "users", set the resource field to "id" // as user resource doesn't reference itself thru a "user" field. field := "user" if route.ResourcePath.Path() == "users" { field = "id" } // Prepent the resource path with the user resource route.ResourcePath.Prepend(m.userResource, field, u) // Go the the next middleware return next(ctx) } } } } // Stop the middleware chain and return a 401 HTTP error headers := http.Header{} headers.Set("WWW-Authenticate", "Basic realm=\"API\"") return ctx, 401, headers, &rest.Error{401, "Please provide proper credentials", nil} }
}, }, }, } ) func SetAuthUserResource(us *resource.Resource) { field, _ := AuthSchema["access"] field.HookParams[0].Param = us } var CheckAccess = func(value interface{}, params []interface{}) interface{} { users, users_ok := params[0].(*resource.Resource) username, u_ok := params[1].(string) password, p_ok := params[2].(string) if users_ok && u_ok && p_ok { l := resource.NewLookup() l.AddQuery(schema.Query{schema.Equal{Field: "username", Value: username}}) list, err := users.Find(context.Background(), l, 1, 1) if err == nil && len(list.Items) == 1 { user := list.Items[0] if schema.VerifyPassword(user.Payload["password"], []byte(password)) { return true } } } return false }