diff --git a/api/openapi/auth.yml b/api/openapi/auth.yml index 0b8882a2..8a308e6b 100644 --- a/api/openapi/auth.yml +++ b/api/openapi/auth.yml @@ -42,7 +42,7 @@ paths: $ref: "#/components/responses/KeyRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -58,7 +58,7 @@ paths: responses: '204': description: Key revoked. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -101,7 +101,7 @@ paths: $ref: "#/components/responses/GroupsPageRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Group does not exist. @@ -122,7 +122,7 @@ paths: $ref: "#/components/responses/GroupRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Group does not exist. @@ -144,7 +144,7 @@ paths: description: Group updated. '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Group does not exist. @@ -169,7 +169,7 @@ paths: description: Group removed. '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Group does not exist. @@ -195,7 +195,7 @@ paths: $ref: "#/components/responses/GroupsPageRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Group does not exist. @@ -221,7 +221,7 @@ paths: $ref: "#/components/responses/GroupsPageRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Group does not exist. @@ -244,7 +244,7 @@ paths: $ref: "#/components/responses/GroupCreateRes" '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '409': description: Failed due to using an existing email address. @@ -264,7 +264,7 @@ paths: responses: '200': $ref: "#/components/responses/MembersRes" - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -285,7 +285,7 @@ paths: description: User group shared with thing group. '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '415': description: Missing or invalid content type. @@ -305,7 +305,7 @@ paths: responses: '200': $ref: "#/components/responses/GroupRes" - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -326,6 +326,10 @@ paths: description: Policies created. '400': description: Failed due to malformed JSON. + '401': + description: Missing or invalid access token provided. + '403': + description: Unauthorized access token provided. '409': description: Failed due to using an existing email address. '415': diff --git a/api/openapi/bootstrap.yml b/api/openapi/bootstrap.yml index 81173834..dd7aa1e8 100644 --- a/api/openapi/bootstrap.yml +++ b/api/openapi/bootstrap.yml @@ -22,7 +22,7 @@ paths: $ref: "#/components/responses/ConfigCreateRes" '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '415': description: Missing or invalid content type. @@ -48,7 +48,7 @@ paths: $ref: "#/components/responses/ConfigListRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -63,7 +63,7 @@ paths: responses: '200': $ref: "#/components/responses/ConfigRes" - '403': + '401': description: Missing or invalid access token provided. '404': description: Config does not exist. @@ -87,7 +87,7 @@ paths: description: Config updated. '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '404': description: Config does not exist. @@ -110,7 +110,7 @@ paths: description: Config removed. '400': description: Failed due to malformed config ID. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -132,7 +132,7 @@ paths: description: Config updated. '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '404': description: Config does not exist. @@ -158,7 +158,7 @@ paths: description: Config updated. '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '404': description: Config does not exist. @@ -179,9 +179,12 @@ paths: responses: '200': $ref: "#/components/responses/BootstrapConfigRes" + '400': + description: Failed due to malformed JSON. + '401': + description: Missing or invalid external key provided. '404': - description: | - Failed to retrieve corresponding config. + description: Failed to retrieve corresponding config. '500': $ref: "#/components/responses/ServiceError" /things/bootstrap/secure/{externalId}: @@ -220,7 +223,7 @@ paths: description: Config removed. '400': description: Failed due to malformed config's ID. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" diff --git a/api/openapi/certs.yml b/api/openapi/certs.yml index a7e2fedc..e6cfb5ea 100644 --- a/api/openapi/certs.yml +++ b/api/openapi/certs.yml @@ -20,6 +20,8 @@ paths: description: Created '400': description: Failed due to malformed JSON. + "401": + description: Missing or invalid access token provided. '500': description: Unexpected server-side error ocurred. /certs/{certID}: @@ -35,6 +37,10 @@ paths: responses: '200': $ref: "#/components/responses/CertRes" + '400': + description: Failed due to malformed query parameters. + "401": + description: Missing or invalid access token provided. '404': description: | Failed to retrieve corresponding certificate. @@ -52,6 +58,8 @@ paths: responses: '200': $ref: "#/components/responses/RevokeRes" + "401": + description: Missing or invalid access token provided. '404': description: | Failed to revoke corresponding certificate. @@ -70,6 +78,10 @@ paths: responses: '200': $ref: "#/components/responses/SerialsPageRes" + '400': + description: Failed due to malformed query parameters. + "401": + description: Missing or invalid access token provided. '404': description: | Failed to retrieve corresponding certificates. diff --git a/api/openapi/consumers-notifiers.yml b/api/openapi/consumers-notifiers.yml index 2afc750f..bd06d805 100644 --- a/api/openapi/consumers-notifiers.yml +++ b/api/openapi/consumers-notifiers.yml @@ -42,7 +42,7 @@ paths: $ref: "#/components/responses/Page" "400": description: Failed due to malformed query parameters. - "403": + "401": description: Missing or invalid access token provided. "500": $ref: "#/components/responses/ServiceError" @@ -59,7 +59,7 @@ paths: responses: "200": $ref: "#/components/responses/View" - "403": + "401": description: Missing or invalid access token provided. "500": $ref: "#/components/responses/ServiceError" @@ -75,7 +75,7 @@ paths: responses: "204": description: Subscription removed - "403": + "401": description: Missing or invalid access token provided. "500": $ref: "#/components/responses/ServiceError" diff --git a/api/openapi/http.yml b/api/openapi/http.yml index 88f32945..6221c91f 100644 --- a/api/openapi/http.yml +++ b/api/openapi/http.yml @@ -24,8 +24,8 @@ paths: description: Message is accepted for processing. "400": description: Message discarded due to its malformed content. - "403": - description: Message discarded due to missing or invalid credentials. + "401": + description: Missing or invalid access token provided. "404": description: Message discarded due to invalid channel id. "415": diff --git a/api/openapi/provision.yml b/api/openapi/provision.yml index 8097c3f5..1c0f9247 100644 --- a/api/openapi/provision.yml +++ b/api/openapi/provision.yml @@ -20,10 +20,10 @@ paths: description: Created '400': description: Failed due to malformed JSON. - '403': - description: Unauthorized. + "401": + description: Missing or invalid access token provided. '500': - description: Unexpected server-side error ocurred. + $ref: "#/components/responses/ServiceError" get: summary: Gets current mapping. description: Gets current mapping. This can be used in UI @@ -36,10 +36,10 @@ paths: responses: '200': $ref: "#/components/responses/ProvisionRes" - '403': - description: Unauthorized. + "401": + description: Missing or invalid access token provided. '500': - description: Unexpected server-side error ocurred. + $ref: "#/components/responses/ServiceError" /health: get: summary: Retrieves service health check info. @@ -81,6 +81,8 @@ components: type: string responses: + ServiceError: + description: Unexpected server-side error occurred. ProvisionRes: description: Current mapping JSON representation. content: diff --git a/api/openapi/readers.yml b/api/openapi/readers.yml index 7e6bd4b8..fa6d3fb4 100644 --- a/api/openapi/readers.yml +++ b/api/openapi/readers.yml @@ -33,7 +33,7 @@ paths: $ref: "#/components/responses/MessagesPageRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" diff --git a/api/openapi/twins.yml b/api/openapi/twins.yml index 4233e169..1442040a 100644 --- a/api/openapi/twins.yml +++ b/api/openapi/twins.yml @@ -22,7 +22,7 @@ paths: $ref: "#/components/responses/TwinCreateRes" '400': description: Failed due to malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '415': description: Missing or invalid content type. @@ -47,7 +47,7 @@ paths: $ref: '#/components/responses/TwinsPageRes' '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: '#/components/responses/ServiceError' @@ -65,7 +65,7 @@ paths: $ref: '#/components/responses/TwinRes' '400': description: Failed due to malformed twin's ID. - '403': + '401': description: Missing or invalid access token provided. '404': description: Twin does not exist. @@ -88,7 +88,7 @@ paths: description: Twin updated. '400': description: Failed due to malformed twin's ID or malformed JSON. - '403': + '401': description: Missing or invalid access token provided. '404': description: Twin does not exist. @@ -109,7 +109,7 @@ paths: description: Twin removed. '400': description: Failed due to malformed twin's ID. - '403': + '401': description: Missing or invalid access token provided '404': description: Twin does not exist. @@ -134,7 +134,7 @@ paths: $ref: '#/components/responses/StatesPageRes' '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '404': description: Twin does not exist. diff --git a/api/openapi/users.yml b/api/openapi/users.yml index 9960de33..600cd42c 100644 --- a/api/openapi/users.yml +++ b/api/openapi/users.yml @@ -20,6 +20,8 @@ paths: $ref: "#/components/responses/UserCreateRes" '400': description: Failed due to malformed JSON. + '401': + description: Missing or invalid access token provided. '409': description: Failed due to using an existing email address. '415': @@ -73,7 +75,7 @@ paths: description: Failed due to malformed JSON. '404': description: Failed due to non existing user. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -92,7 +94,7 @@ paths: $ref: "#/components/responses/UserRes" '400': description: Failed due to malformed query parameters. - '403': + '401': description: Missing or invalid access token provided. '500': $ref: "#/components/responses/ServiceError" @@ -146,7 +148,7 @@ paths: application/json: schema: $ref: '#/components/schemas/Error' - '403': + '401': description: Failed due to using invalid credentials. content: application/json: diff --git a/auth/api/grpc/endpoint_test.go b/auth/api/grpc/endpoint_test.go index 4408e131..3b57cf6e 100644 --- a/auth/api/grpc/endpoint_test.go +++ b/auth/api/grpc/endpoint_test.go @@ -109,11 +109,12 @@ func TestIssue(t *testing.T) { code: codes.InvalidArgument, }, { - desc: "issue for user that exist", - id: "", - kind: auth.APIKey, - err: status.Error(codes.Unauthenticated, "unauthorized access"), - code: codes.Unauthenticated, + desc: "issue for user that exist", + id: "", + email: "", + kind: auth.APIKey, + err: status.Error(codes.Unauthenticated, "unauthenticated access"), + code: codes.Unauthenticated, }, } @@ -171,7 +172,7 @@ func TestIdentify(t *testing.T) { desc: "identify user with invalid user token", token: "invalid", idt: mainflux.UserIdentity{}, - err: status.Error(codes.Unauthenticated, "unauthorized access"), + err: status.Error(codes.Unauthenticated, "unauthenticated access"), code: codes.Unauthenticated, }, { @@ -230,7 +231,7 @@ func TestAuthorize(t *testing.T) { relation: "unauthorizedRelation", ar: mainflux.AuthorizeRes{Authorized: false}, err: nil, - code: codes.Unauthenticated, + code: codes.PermissionDenied, }, { desc: "authorize user with unauthorized object", @@ -240,7 +241,7 @@ func TestAuthorize(t *testing.T) { relation: memberRelation, ar: mainflux.AuthorizeRes{Authorized: false}, err: nil, - code: codes.Unauthenticated, + code: codes.PermissionDenied, }, { desc: "authorize user with unauthorized subject", @@ -250,7 +251,7 @@ func TestAuthorize(t *testing.T) { relation: memberRelation, ar: mainflux.AuthorizeRes{Authorized: false}, err: nil, - code: codes.Unauthenticated, + code: codes.PermissionDenied, }, { desc: "authorize user with invalid ACL", diff --git a/auth/api/grpc/requests.go b/auth/api/grpc/requests.go index 1490c901..e4e322e8 100644 --- a/auth/api/grpc/requests.go +++ b/auth/api/grpc/requests.go @@ -34,7 +34,7 @@ type issueReq struct { func (req issueReq) validate() error { if req.email == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.keyType != auth.LoginKey && req.keyType != auth.APIKey && @@ -54,7 +54,7 @@ type assignReq struct { func (req assignReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.groupID == "" || req.memberID == "" { return errors.ErrMalformedEntity @@ -72,7 +72,7 @@ type membersReq struct { func (req membersReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.groupID == "" { return errors.ErrMalformedEntity diff --git a/auth/api/grpc/server.go b/auth/api/grpc/server.go index 48754479..a8314c47 100644 --- a/auth/api/grpc/server.go +++ b/auth/api/grpc/server.go @@ -238,9 +238,10 @@ func encodeError(err error) error { return nil case errors.Contains(err, errors.ErrMalformedEntity): return status.Error(codes.InvalidArgument, "received invalid token request") - case errors.Contains(err, errors.ErrUnauthorizedAccess), - errors.Contains(err, errors.ErrAuthorization): + case errors.Contains(err, errors.ErrAuthentication): return status.Error(codes.Unauthenticated, err.Error()) + case errors.Contains(err, errors.ErrAuthorization): + return status.Error(codes.PermissionDenied, err.Error()) case errors.Contains(err, auth.ErrKeyExpired): return status.Error(codes.Unauthenticated, err.Error()) default: diff --git a/auth/api/http/groups/endpoint_test.go b/auth/api/http/groups/endpoint_test.go index 21bb74df..fa9b3307 100644 --- a/auth/api/http/groups/endpoint_test.go +++ b/auth/api/http/groups/endpoint_test.go @@ -154,7 +154,7 @@ func TestShareGroupAccess(t *testing.T) { contentType: contentType, auth: "token", userGroupID: "ug", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, } diff --git a/auth/api/http/groups/requests.go b/auth/api/http/groups/requests.go index c4be6743..6b157ae1 100644 --- a/auth/api/http/groups/requests.go +++ b/auth/api/http/groups/requests.go @@ -15,7 +15,7 @@ type createGroupReq struct { func (req createGroupReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if len(req.Name) > maxNameSize || req.Name == "" { return errors.Wrap(errors.ErrMalformedEntity, auth.ErrBadGroupName) @@ -34,7 +34,7 @@ type updateGroupReq struct { func (req updateGroupReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -56,7 +56,7 @@ type listGroupsReq struct { func (req listGroupsReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.level > auth.MaxLevel || req.level < auth.MinLevel { @@ -78,7 +78,7 @@ type listMembersReq struct { func (req listMembersReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -98,7 +98,7 @@ type listMembershipsReq struct { func (req listMembershipsReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -117,7 +117,7 @@ type assignReq struct { func (req assignReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.Type == "" || req.groupID == "" || len(req.Members) == 0 { @@ -135,7 +135,7 @@ type shareGroupAccessReq struct { func (req shareGroupAccessReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.ThingGroupID == "" || req.userGroupID == "" { @@ -151,7 +151,7 @@ type unassignReq struct { func (req unassignReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.groupID == "" || len(req.Members) == 0 { @@ -168,7 +168,7 @@ type groupReq struct { func (req groupReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { diff --git a/auth/api/http/groups/transport.go b/auth/api/http/groups/transport.go index e910777b..8efae113 100644 --- a/auth/api/http/groups/transport.go +++ b/auth/api/http/groups/transport.go @@ -317,8 +317,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { switch { case errors.Contains(err, errors.ErrMalformedEntity): w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrUnauthorizedAccess): - w.WriteHeader(http.StatusForbidden) + case errors.Contains(err, errors.ErrAuthentication): + w.WriteHeader(http.StatusUnauthorized) case errors.Contains(err, errors.ErrNotFound): w.WriteHeader(http.StatusNotFound) case errors.Contains(err, errors.ErrConflict): diff --git a/auth/api/http/keys/endpoint_test.go b/auth/api/http/keys/endpoint_test.go index 7b4367e1..66a76df3 100644 --- a/auth/api/http/keys/endpoint_test.go +++ b/auth/api/http/keys/endpoint_test.go @@ -109,7 +109,7 @@ func TestIssue(t *testing.T) { req: toJSON(lk), ct: contentType, token: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "issue API key", @@ -123,7 +123,7 @@ func TestIssue(t *testing.T) { req: toJSON(rk), ct: contentType, token: loginSecret, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "issue login key wrong content type", @@ -140,18 +140,18 @@ func TestIssue(t *testing.T) { status: http.StatusUnsupportedMediaType, }, { - desc: "issue key unauthorized", + desc: "issue key with an invalid token", req: toJSON(ak), ct: contentType, token: "wrong", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "issue recovery key with empty token", req: toJSON(rk), ct: contentType, token: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "issue key with invalid request", @@ -223,10 +223,10 @@ func TestRetrieve(t *testing.T) { status: http.StatusNotFound, }, { - desc: "retrieve a key unauthorized", + desc: "retrieve a key with an invalid token", id: k.ID, token: "wrong", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, } @@ -275,10 +275,10 @@ func TestRevoke(t *testing.T) { status: http.StatusNoContent, }, { - desc: "revoke a key unauthorized", + desc: "revoke key with invalid token", id: k.ID, token: "wrong", - status: http.StatusForbidden}, + status: http.StatusUnauthorized}, } for _, tc := range cases { diff --git a/auth/api/http/keys/requests.go b/auth/api/http/keys/requests.go index d87cd246..8cc379e2 100644 --- a/auth/api/http/keys/requests.go +++ b/auth/api/http/keys/requests.go @@ -19,7 +19,7 @@ type issueKeyReq struct { // It is not possible to issue Reset key using HTTP API. func (req issueKeyReq) validate() error { if req.Type != auth.APIKey || req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil } diff --git a/auth/api/http/keys/transport.go b/auth/api/http/keys/transport.go index 57dcd7c2..761109ba 100644 --- a/auth/api/http/keys/transport.go +++ b/auth/api/http/keys/transport.go @@ -94,8 +94,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { switch { case errors.Contains(err, errors.ErrMalformedEntity): w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrUnauthorizedAccess): - w.WriteHeader(http.StatusForbidden) + case errors.Contains(err, errors.ErrAuthentication): + w.WriteHeader(http.StatusUnauthorized) case errors.Contains(err, errors.ErrNotFound): w.WriteHeader(http.StatusNotFound) case errors.Contains(err, errors.ErrConflict): diff --git a/auth/api/http/policies/endpoint_test.go b/auth/api/http/policies/endpoint_test.go index cef65c69..cf8e66f6 100644 --- a/auth/api/http/policies/endpoint_test.go +++ b/auth/api/http/policies/endpoint_test.go @@ -138,14 +138,14 @@ func TestAddPolicies(t *testing.T) { desc: "Add policies with invalid token", token: "invalid", ct: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, req: toJSON(valid), }, { desc: "Add policies with empty token", token: "", ct: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, req: toJSON(valid), }, { @@ -248,14 +248,14 @@ func TestDeletePolicies(t *testing.T) { desc: "Delete policies with invalid token", token: "invalid", ct: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, req: toJSON(validSingleDeleteReq), }, { desc: "Delete policies with empty token", token: "", ct: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, req: toJSON(validSingleDeleteReq), }, { diff --git a/auth/api/http/policies/requests.go b/auth/api/http/policies/requests.go index cec4fc7a..f4785e3e 100644 --- a/auth/api/http/policies/requests.go +++ b/auth/api/http/policies/requests.go @@ -35,7 +35,7 @@ type policiesReq struct { func (req policiesReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if len(req.SubjectIDs) == 0 || len(req.Policies) == 0 || req.Object == "" { diff --git a/auth/api/http/policies/transport.go b/auth/api/http/policies/transport.go index 44fa35ec..2aa546f5 100644 --- a/auth/api/http/policies/transport.go +++ b/auth/api/http/policies/transport.go @@ -77,8 +77,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { switch { case errors.Contains(err, errors.ErrMalformedEntity): w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errors.ErrUnauthorizedAccess): - w.WriteHeader(http.StatusForbidden) + case errors.Contains(err, errors.ErrAuthentication): + w.WriteHeader(http.StatusUnauthorized) case errors.Contains(err, errors.ErrNotFound): w.WriteHeader(http.StatusNotFound) case errors.Contains(err, errors.ErrConflict): diff --git a/auth/jwt/token_test.go b/auth/jwt/token_test.go index 491a1e18..ada6dae8 100644 --- a/auth/jwt/token_test.go +++ b/auth/jwt/token_test.go @@ -83,7 +83,7 @@ func TestParse(t *testing.T) { desc: "parse ivalid key", key: auth.Key{}, token: "invalid", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "parse expired key", diff --git a/auth/jwt/tokenizer.go b/auth/jwt/tokenizer.go index bad6e470..29a32315 100644 --- a/auth/jwt/tokenizer.go +++ b/auth/jwt/tokenizer.go @@ -62,7 +62,7 @@ func (svc tokenizer) Parse(token string) (auth.Key, error) { c := claims{} _, err := jwt.ParseWithClaims(token, &c, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } return []byte(svc.secret), nil }) @@ -75,7 +75,7 @@ func (svc tokenizer) Parse(token string) (auth.Key, error) { } return auth.Key{}, errors.Wrap(auth.ErrKeyExpired, err) } - return auth.Key{}, errors.Wrap(errors.ErrUnauthorizedAccess, err) + return auth.Key{}, errors.Wrap(errors.ErrAuthentication, err) } return c.toKey(), nil diff --git a/auth/postgres/key_test.go b/auth/postgres/key_test.go index 14f2929f..db2d095a 100644 --- a/auth/postgres/key_test.go +++ b/auth/postgres/key_test.go @@ -98,13 +98,13 @@ func TestKeyRetrieve(t *testing.T) { err: nil, }, { - desc: "retrieve unauthorized", + desc: "retrieve key with empty issuer id", id: key.ID, owner: "", err: errors.ErrNotFound, }, { - desc: "retrieve unknown key", + desc: "retrieve non-existent key", id: "", owner: key.IssuerID, err: errors.ErrNotFound, diff --git a/auth/service.go b/auth/service.go index d96d7a28..546ad4a7 100644 --- a/auth/service.go +++ b/auth/service.go @@ -153,11 +153,11 @@ func (svc service) Identify(ctx context.Context, token string) (Identity, error) case APIKey: _, err := svc.keys.Retrieve(context.TODO(), key.IssuerID, key.ID) if err != nil { - return Identity{}, errors.ErrUnauthorizedAccess + return Identity{}, errors.ErrAuthentication } return Identity{ID: key.IssuerID, Email: key.Subject}, nil default: - return Identity{}, errors.ErrUnauthorizedAccess + return Identity{}, errors.ErrAuthentication } } @@ -281,7 +281,7 @@ func (svc service) login(token string) (string, string, error) { } // Only login key token is valid for login. if key.Type != LoginKey || key.IssuerID == "" { - return "", "", errors.ErrUnauthorizedAccess + return "", "", errors.ErrAuthentication } return key.IssuerID, key.Subject, nil diff --git a/auth/service_test.go b/auth/service_test.go index b1b17030..53e34fd2 100644 --- a/auth/service_test.go +++ b/auth/service_test.go @@ -83,13 +83,13 @@ func TestIssue(t *testing.T) { err: nil, }, { - desc: "issue API key unauthorized", + desc: "issue API key with an invalid token", key: auth.Key{ Type: auth.APIKey, IssuedAt: time.Now(), }, token: "invalid", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "issue API key with no time", @@ -156,10 +156,10 @@ func TestRevoke(t *testing.T) { err: nil, }, { - desc: "revoke unauthorized", + desc: "revoke with empty login key", id: newKey.ID, token: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -209,22 +209,22 @@ func TestRetrieve(t *testing.T) { err: errors.ErrNotFound, }, { - desc: "retrieve unauthorized", + desc: "retrieve with wrong login key", id: apiKey.ID, token: "wrong", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "retrieve with API token", id: apiKey.ID, token: apiToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "retrieve with reset token", id: apiKey.ID, token: resetToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -287,13 +287,13 @@ func TestIdentify(t *testing.T) { desc: "identify expired key", key: invalidSecret, idt: auth.Identity{}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "identify invalid key", key: "invalid", idt: auth.Identity{}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -478,10 +478,10 @@ func TestViewGroup(t *testing.T) { err: nil, }, { - desc: "view group with unauthorized token", + desc: "view group with invalid token", token: "wrongtoken", groupID: group.ID, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "view group for wrong id", @@ -552,7 +552,7 @@ func TestListGroups(t *testing.T) { token: "wrongToken", level: 5, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -618,7 +618,7 @@ func TestListChildren(t *testing.T) { token: "wrongToken", level: 5, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -683,7 +683,7 @@ func TestListParents(t *testing.T) { token: "wrongToken", level: 5, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -760,7 +760,7 @@ func TestListMembers(t *testing.T) { offset: 0, limit: n, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -840,7 +840,7 @@ func TestListMemberships(t *testing.T) { offset: 0, limit: n, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -883,7 +883,7 @@ func TestRemoveGroup(t *testing.T) { require.Nil(t, err, fmt.Sprintf("group save got unexpected error: %s", err)) err = svc.RemoveGroup(context.Background(), "wrongToken", group.ID) - assert.True(t, errors.Contains(err, errors.ErrUnauthorizedAccess), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrUnauthorizedAccess, err)) + assert.True(t, errors.Contains(err, errors.ErrAuthentication), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrAuthentication, err)) err = svc.RemoveGroup(context.Background(), apiToken, "wrongID") assert.True(t, errors.Contains(err, auth.ErrGroupNotFound), fmt.Sprintf("Remove group with wrong id: expected %v got %v", auth.ErrGroupNotFound, err)) @@ -951,7 +951,7 @@ func TestAssign(t *testing.T) { assert.True(t, mp.Total == 1, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 1, mp.Total)) err = svc.Assign(context.Background(), "wrongToken", group.ID, "things", mid) - assert.True(t, errors.Contains(err, errors.ErrUnauthorizedAccess), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrUnauthorizedAccess, err)) + assert.True(t, errors.Contains(err, errors.ErrAuthentication), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrAuthentication, err)) } @@ -1003,7 +1003,7 @@ func TestUnassign(t *testing.T) { assert.True(t, mp.Total == 0, fmt.Sprintf("retrieve members of a group: expected %d got %d\n", 0, mp.Total)) err = svc.Unassign(context.Background(), "wrongToken", group.ID, mid) - assert.True(t, errors.Contains(err, errors.ErrUnauthorizedAccess), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrUnauthorizedAccess, err)) + assert.True(t, errors.Contains(err, errors.ErrAuthentication), fmt.Sprintf("Unauthorized access: expected %v got %v", errors.ErrAuthentication, err)) err = svc.Unassign(context.Background(), apiToken, group.ID, mid) assert.True(t, errors.Contains(err, auth.ErrGroupNotFound), fmt.Sprintf("Unauthorized access: expected %v got %v", nil, err)) diff --git a/bootstrap/api/endpoint_test.go b/bootstrap/api/endpoint_test.go index 61a5c87a..5a08c29c 100644 --- a/bootstrap/api/endpoint_test.go +++ b/bootstrap/api/endpoint_test.go @@ -81,11 +81,12 @@ var ( CACert: "newca", } - bsErrorRes = toJSON(errorRes{bootstrap.ErrBootstrap.Error()}) - unauthRes = toJSON(errorRes{errors.ErrUnauthorizedAccess.Error()}) - malformedRes = toJSON(errorRes{errors.ErrMalformedEntity.Error()}) - extKeyNotFoundRes = toJSON(errorRes{bootstrap.ErrExternalKeyNotFound.Error()}) - extSecKeyNotFoundRes = toJSON(errorRes{bootstrap.ErrSecureBootstrap.Error()}) + bsErrorRes = toJSON(errorRes{bootstrap.ErrBootstrap.Error()}) + authnRes = toJSON(errorRes{errors.ErrAuthentication.Error()}) + authzRes = toJSON(errorRes{errors.ErrAuthorization.Error()}) + malformedRes = toJSON(errorRes{errors.ErrMalformedEntity.Error()}) + extKeyRes = toJSON(errorRes{bootstrap.ErrExternalKey.Error()}) + extSecKeyRes = toJSON(errorRes{bootstrap.ErrExternalKeySecure.Error()}) ) type testRequest struct { @@ -226,11 +227,11 @@ func TestAdd(t *testing.T) { location string }{ { - desc: "add a config unauthorized", + desc: "add a config with invalid token", req: data, auth: invalidToken, contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, location: "", }, { @@ -369,10 +370,10 @@ func TestView(t *testing.T) { res config }{ { - desc: "view a config unauthorized", + desc: "view a config with invalid token", auth: invalidToken, id: saved.MFThing, - status: http.StatusForbidden, + status: http.StatusUnauthorized, res: config{}, }, { @@ -393,7 +394,7 @@ func TestView(t *testing.T) { desc: "view a config with an empty token", auth: "", id: saved.MFThing, - status: http.StatusForbidden, + status: http.StatusUnauthorized, res: config{}, }, } @@ -445,12 +446,12 @@ func TestUpdate(t *testing.T) { status int }{ { - desc: "update unauthorized", + desc: "update with invalid token", req: data, id: saved.MFThing, auth: invalidToken, contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update with an empty token", @@ -458,7 +459,7 @@ func TestUpdate(t *testing.T) { id: saved.MFThing, auth: "", contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update a valid config", @@ -539,12 +540,12 @@ func TestUpdateCert(t *testing.T) { status int }{ { - desc: "update unauthorized", + desc: "update with invalid token", req: data, id: saved.MFThing, auth: invalidToken, contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update with an empty token", @@ -552,7 +553,7 @@ func TestUpdateCert(t *testing.T) { id: saved.MFThing, auth: "", contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update a valid config", @@ -639,12 +640,12 @@ func TestUpdateConnections(t *testing.T) { status int }{ { - desc: "update connections unauthorized", + desc: "update connections with invalid token", req: data, id: saved.MFThing, auth: invalidToken, contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update connections with an empty token", @@ -652,7 +653,7 @@ func TestUpdateConnections(t *testing.T) { id: saved.MFThing, auth: "", contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update connections valid config", @@ -783,17 +784,17 @@ func TestList(t *testing.T) { res configPage }{ { - desc: "view list unauthorized", + desc: "view list with invalid token", auth: invalidToken, url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 0, 10), - status: http.StatusForbidden, + status: http.StatusUnauthorized, res: configPage{}, }, { desc: "view list with an empty token", auth: "", url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 0, 10), - status: http.StatusForbidden, + status: http.StatusUnauthorized, res: configPage{}, }, { @@ -991,15 +992,15 @@ func TestRemove(t *testing.T) { status int }{ { - desc: "remove unauthorized", + desc: "remove with invalid token", id: saved.MFThing, auth: invalidToken, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "remove with an empty token", id: saved.MFThing, auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "remove non-existing config", @@ -1102,16 +1103,16 @@ func TestBootstrap(t *testing.T) { desc: "bootstrap a Thing with unknown key", externalID: c.ExternalID, externalKey: unknown, - status: http.StatusNotFound, - res: extKeyNotFoundRes, + status: http.StatusForbidden, + res: extKeyRes, secure: false, }, { desc: "bootstrap a Thing with an empty key", externalID: c.ExternalID, externalKey: "", - status: http.StatusForbidden, - res: unauthRes, + status: http.StatusUnauthorized, + res: authnRes, secure: false, }, { @@ -1134,8 +1135,8 @@ func TestBootstrap(t *testing.T) { desc: "bootstrap secure with unencrypted key", externalID: fmt.Sprintf("secure/%s", c.ExternalID), externalKey: c.ExternalKey, - status: http.StatusNotFound, - res: extSecKeyNotFoundRes, + status: http.StatusForbidden, + res: extSecKeyRes, secure: true, }, } @@ -1186,12 +1187,12 @@ func TestChangeState(t *testing.T) { status int }{ { - desc: "change state unauthorized", + desc: "change state with invalid token", id: saved.MFThing, auth: invalidToken, state: active, contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "change state with an empty token", @@ -1199,7 +1200,7 @@ func TestChangeState(t *testing.T) { auth: "", state: active, contentType: contentType, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "change state with invalid content type", diff --git a/bootstrap/api/requests.go b/bootstrap/api/requests.go index 3206cb7f..a374bd15 100644 --- a/bootstrap/api/requests.go +++ b/bootstrap/api/requests.go @@ -27,7 +27,7 @@ type addReq struct { func (req addReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.ExternalID == "" || req.ExternalKey == "" { @@ -44,7 +44,7 @@ type entityReq struct { func (req entityReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -63,7 +63,7 @@ type updateReq struct { func (req updateReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -83,7 +83,7 @@ type updateCertReq struct { func (req updateCertReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.thingID == "" { @@ -101,7 +101,7 @@ type updateConnReq struct { func (req updateConnReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -120,7 +120,7 @@ type listReq struct { func (req listReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.limit == 0 || req.limit > maxLimit { @@ -137,7 +137,7 @@ type bootstrapReq struct { func (req bootstrapReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -155,7 +155,7 @@ type changeStateReq struct { func (req changeStateReq) validate() error { if req.key == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { diff --git a/bootstrap/api/requests_test.go b/bootstrap/api/requests_test.go index e02c812a..a5555ee4 100644 --- a/bootstrap/api/requests_test.go +++ b/bootstrap/api/requests_test.go @@ -22,7 +22,7 @@ func TestAddReqValidation(t *testing.T) { token: "", externalID: "external-id", externalKey: "external-key", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty external ID", @@ -63,7 +63,7 @@ func TestEntityReqValidation(t *testing.T) { desc: "empty key", key: "", id: "id", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty id", @@ -94,7 +94,7 @@ func TestUpdateReqValidation(t *testing.T) { desc: "empty key", key: "", id: "id", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty id", @@ -126,7 +126,7 @@ func TestUpdateCertReqValidation(t *testing.T) { desc: "empty key", key: "", thingID: "thingID", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty thing key", @@ -158,7 +158,7 @@ func TestUpdateConnReqValidation(t *testing.T) { desc: "empty key", key: "", id: "id", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty id", @@ -192,7 +192,7 @@ func TestListReqValidation(t *testing.T) { key: "", offset: 0, limit: 1, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "too large limit", @@ -233,7 +233,7 @@ func TestBootstrapReqValidation(t *testing.T) { desc: "empty external key", externKey: "", externID: "id", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty external id", @@ -267,7 +267,7 @@ func TestChangeStateReqValidation(t *testing.T) { key: "", id: "id", state: bootstrap.State(1), - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "empty id", diff --git a/bootstrap/api/transport.go b/bootstrap/api/transport.go index ab9abc32..a757c496 100644 --- a/bootstrap/api/transport.go +++ b/bootstrap/api/transport.go @@ -261,7 +261,11 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { w.WriteHeader(http.StatusBadRequest) case errors.Contains(errorVal, errors.ErrNotFound): w.WriteHeader(http.StatusNotFound) - case errors.Contains(errorVal, errors.ErrUnauthorizedAccess): + case errors.Contains(errorVal, errors.ErrAuthentication): + w.WriteHeader(http.StatusUnauthorized) + case errors.Contains(errorVal, bootstrap.ErrExternalKey), + errors.Contains(errorVal, bootstrap.ErrExternalKeySecure), + errors.Contains(errorVal, errors.ErrAuthorization): w.WriteHeader(http.StatusForbidden) case errors.Contains(errorVal, errors.ErrConflict): w.WriteHeader(http.StatusConflict) diff --git a/bootstrap/mocks/configs.go b/bootstrap/mocks/configs.go index f24f7910..98d9966a 100644 --- a/bootstrap/mocks/configs.go +++ b/bootstrap/mocks/configs.go @@ -73,7 +73,7 @@ func (crm *configRepositoryMock) RetrieveByID(token, id string) (bootstrap.Confi return bootstrap.Config{}, errors.ErrNotFound } if c.Owner != token { - return bootstrap.Config{}, errors.ErrUnauthorizedAccess + return bootstrap.Config{}, errors.ErrAuthentication } return c, nil @@ -227,7 +227,7 @@ func (crm *configRepositoryMock) ChangeState(token, id string, state bootstrap.S return errors.ErrNotFound } if config.Owner != token { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } config.State = state diff --git a/bootstrap/mocks/things.go b/bootstrap/mocks/things.go index 5adda442..9aa07e48 100644 --- a/bootstrap/mocks/things.go +++ b/bootstrap/mocks/things.go @@ -41,7 +41,7 @@ func (svc *mainfluxThings) CreateThings(_ context.Context, owner string, ths ... userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { - return []things.Thing{}, errors.ErrUnauthorizedAccess + return []things.Thing{}, errors.ErrAuthentication } for i := range ths { svc.counter++ @@ -60,7 +60,7 @@ func (svc *mainfluxThings) ViewThing(_ context.Context, owner, id string) (thing userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { - return things.Thing{}, errors.ErrUnauthorizedAccess + return things.Thing{}, errors.ErrAuthentication } if t, ok := svc.things[id]; ok && t.Owner == userID.Email { @@ -77,11 +77,11 @@ func (svc *mainfluxThings) Connect(_ context.Context, owner string, chIDs, thIDs userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } for _, chID := range chIDs { if svc.channels[chID].Owner != userID.Email { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } for _, thID := range thIDs { svc.connections[chID] = append(svc.connections[chID], thID) @@ -97,12 +97,12 @@ func (svc *mainfluxThings) Disconnect(_ context.Context, owner string, chIDs, th userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } for _, chID := range chIDs { if svc.channels[chID].Owner != userID.Email { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } ids := svc.connections[chID] @@ -132,7 +132,7 @@ func (svc *mainfluxThings) RemoveThing(_ context.Context, owner, id string) erro userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if t, ok := svc.things[id]; !ok || t.Owner != userID.Email { @@ -189,7 +189,7 @@ func (svc *mainfluxThings) CreateChannels(_ context.Context, owner string, chs . userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { - return []things.Channel{}, errors.ErrUnauthorizedAccess + return []things.Channel{}, errors.ErrAuthentication } for i := range chs { svc.counter++ diff --git a/bootstrap/mocks/users.go b/bootstrap/mocks/users.go index 748bf6b3..54942d69 100644 --- a/bootstrap/mocks/users.go +++ b/bootstrap/mocks/users.go @@ -27,7 +27,7 @@ func (svc serviceMock) Identify(ctx context.Context, in *mainflux.Token, opts .. if id, ok := svc.users[in.Value]; ok { return &mainflux.UserIdentity{Email: id, Id: id}, nil } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc serviceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { @@ -37,7 +37,7 @@ func (svc serviceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts .. return &mainflux.Token{Value: id}, nil } } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc serviceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { diff --git a/bootstrap/redis/producer/streams_test.go b/bootstrap/redis/producer/streams_test.go index 1ac4b8fa..102fb2cc 100644 --- a/bootstrap/redis/producer/streams_test.go +++ b/bootstrap/redis/producer/streams_test.go @@ -371,7 +371,7 @@ func TestRemove(t *testing.T) { desc: "remove config with invalid credentials", id: saved.MFThing, token: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, event: nil, }, } @@ -435,7 +435,7 @@ func TestBootstrap(t *testing.T) { desc: "bootstrap with an error", externalID: saved.ExternalID, externalKey: "external", - err: errors.ErrNotFound, + err: bootstrap.ErrExternalKey, event: map[string]interface{}{ "external_id": saved.ExternalID, "success": "0", @@ -507,7 +507,7 @@ func TestChangeState(t *testing.T) { id: saved.MFThing, token: "", state: bootstrap.Inactive, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, event: nil, }, } diff --git a/bootstrap/service.go b/bootstrap/service.go index 7e382e62..93f67b8b 100644 --- a/bootstrap/service.go +++ b/bootstrap/service.go @@ -17,14 +17,14 @@ import ( var ( // ErrThings indicates failure to communicate with Mainflux Things service. - // It can be due to networking error or invalid/unauthorized request. + // It can be due to networking error or invalid/unauthenticated request. ErrThings = errors.New("failed to receive response from Things service") - // ErrExternalKeyNotFound indicates a non-existent bootstrap configuration for given external key - ErrExternalKeyNotFound = errors.New("failed to get bootstrap configuration for given external key") + // ErrExternalKey indicates a non-existent bootstrap configuration for given external key + ErrExternalKey = errors.New("failed to get bootstrap configuration for given external key") - // ErrSecureBootstrap indicates error in getting bootstrap configuration for given encrypted external key - ErrSecureBootstrap = errors.New("failed to get bootstrap configuration for given encrypted external key") + // ErrExternalKeySecure indicates error in getting bootstrap configuration for given encrypted external key + ErrExternalKeySecure = errors.New("failed to get bootstrap configuration for given encrypted external key") // ErrBootstrap indicates error in getting bootstrap configuration. ErrBootstrap = errors.New("failed to read bootstrap configuration") @@ -284,13 +284,13 @@ func (bs bootstrapService) Bootstrap(ctx context.Context, externalKey, externalI if secure { dec, err := bs.dec(externalKey) if err != nil { - return Config{}, errors.Wrap(ErrSecureBootstrap, err) + return Config{}, errors.Wrap(ErrExternalKeySecure, err) } externalKey = dec } if cfg.ExternalKey != externalKey { - return Config{}, errors.Wrap(ErrExternalKeyNotFound, errors.ErrNotFound) + return Config{}, ErrExternalKey } return cfg, nil @@ -372,7 +372,7 @@ func (bs bootstrapService) identify(token string) (string, error) { res, err := bs.auth.Identify(ctx, &mainflux.Token{Value: token}) if err != nil { - return "", errors.ErrUnauthorizedAccess + return "", errors.ErrAuthentication } return res.GetEmail(), nil @@ -477,14 +477,14 @@ func (bs bootstrapService) toIDList(channels []Channel) []string { func (bs bootstrapService) dec(in string) (string, error) { ciphertext, err := hex.DecodeString(in) if err != nil { - return "", errors.ErrNotFound + return "", err } block, err := aes.NewCipher(bs.encKey) if err != nil { return "", err } if len(ciphertext) < aes.BlockSize { - return "", errors.ErrMalformedEntity + return "", err } iv := ciphertext[:aes.BlockSize] ciphertext = ciphertext[aes.BlockSize:] diff --git a/bootstrap/service_test.go b/bootstrap/service_test.go index b8375e0d..83fd9864 100644 --- a/bootstrap/service_test.go +++ b/bootstrap/service_test.go @@ -134,7 +134,7 @@ func TestAdd(t *testing.T) { desc: "add a config with wrong credentials", config: config, token: invalidToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "add a config with invalid list of channels", @@ -181,7 +181,7 @@ func TestView(t *testing.T) { desc: "view a config with wrong credentials", id: config.MFThing, token: invalidToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -233,7 +233,7 @@ func TestUpdate(t *testing.T) { desc: "update a config with wrong credentials", config: saved, token: invalidToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -291,7 +291,7 @@ func TestUpdateCert(t *testing.T) { clientKey: "newKey", caCert: "newCert", token: invalidToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -365,7 +365,7 @@ func TestUpdateConnections(t *testing.T) { token: invalidToken, id: created.MFKey, connections: []string{"2", "3"}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -437,13 +437,13 @@ func TestList(t *testing.T) { err: nil, }, { - desc: "list configs unauthorized", + desc: "list configs with invalid token", config: bootstrap.ConfigsPage{}, filter: bootstrap.Filter{}, token: invalidToken, offset: 0, limit: 10, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "list last page", @@ -502,7 +502,7 @@ func TestRemove(t *testing.T) { desc: "view a config with wrong credentials", id: saved.MFThing, token: invalidToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "remove an existing config", @@ -563,7 +563,7 @@ func TestBootstrap(t *testing.T) { config: bootstrap.Config{}, externalID: saved.ExternalID, externalKey: "invalid", - err: errors.ErrNotFound, + err: bootstrap.ErrExternalKey, encrypted: false, }, { @@ -612,7 +612,7 @@ func TestChangeState(t *testing.T) { state: bootstrap.Active, id: saved.MFThing, token: invalidToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "change state of non-existing config", diff --git a/certs/api/requests.go b/certs/api/requests.go index 5f0ca9b7..18534692 100644 --- a/certs/api/requests.go +++ b/certs/api/requests.go @@ -18,11 +18,11 @@ type addCertsReq struct { } func (req addCertsReq) validate() error { - if req.ThingID == "" && req.token == "" { - return errUnauthorized + if req.token == "" { + return errors.ErrAuthentication } - if req.TTL == "" || req.KeyType == "" || req.KeyBits == 0 { + if req.ThingID == "" || req.TTL == "" || req.KeyType == "" || req.KeyBits == 0 { return errors.ErrMalformedEntity } return nil @@ -37,7 +37,7 @@ type listReq struct { func (req *listReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.limit == 0 || req.limit > maxLimitSize { return errors.ErrMalformedEntity @@ -52,7 +52,7 @@ type viewReq struct { func (req *viewReq) validate() error { if req.token == "" { - return errUnauthorized + return errors.ErrAuthentication } if req.serialID == "" { return errors.ErrMalformedEntity @@ -67,8 +67,12 @@ type revokeReq struct { } func (req *revokeReq) validate() error { - if req.token == "" || req.certID == "" { - return errors.ErrUnauthorizedAccess + if req.token == "" { + return errors.ErrAuthentication + } + + if req.certID == "" { + return errors.ErrMalformedEntity } return nil diff --git a/certs/api/transport.go b/certs/api/transport.go index 935b7f42..63643ca9 100644 --- a/certs/api/transport.go +++ b/certs/api/transport.go @@ -26,11 +26,6 @@ const ( defLimit = 10 ) -var ( - errUnauthorized = errors.New("missing or invalid credentials provided") - errConflict = errors.New("entity already exists") -) - // MakeHandler returns a HTTP handler for API endpoints. func MakeHandler(svc certs.Service) http.Handler { opts := []kithttp.ServerOption{ @@ -149,7 +144,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { case io.EOF, errors.ErrMalformedEntity, errors.ErrInvalidQueryParams: w.WriteHeader(http.StatusBadRequest) - case errConflict: + case errors.ErrConflict: w.WriteHeader(http.StatusConflict) default: switch err.(type) { diff --git a/certs/service_test.go b/certs/service_test.go index e1981b82..81938888 100644 --- a/certs/service_test.go +++ b/certs/service_test.go @@ -152,7 +152,7 @@ func TestIssueCert(t *testing.T) { ttl: ttl, key: key, keyBits: 2048, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "issue new cert for bad key bits", @@ -208,7 +208,7 @@ func TestRevokeCert(t *testing.T) { desc: "revoke cert for invalid token", token: wrongValue, thingID: thingID, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "revoke cert for invalid thing id", @@ -259,7 +259,7 @@ func TestListCerts(t *testing.T) { offset: 0, limit: certNum, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "list half certs with valid token", @@ -332,7 +332,7 @@ func TestListSerials(t *testing.T) { offset: 0, limit: certNum, certs: nil, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "list half certs with valid token", @@ -394,7 +394,7 @@ func TestViewCert(t *testing.T) { token: wrongValue, serialID: cert.Serial, cert: certs.Cert{}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "list cert with invalid serial", diff --git a/consumers/notifiers/api/endpoint_test.go b/consumers/notifiers/api/endpoint_test.go index 3ac049e2..b3e1f5ce 100644 --- a/consumers/notifiers/api/endpoint_test.go +++ b/consumers/notifiers/api/endpoint_test.go @@ -36,7 +36,7 @@ const ( var ( notFoundRes = toJSON(errorRes{errors.ErrNotFound.Error()}) - unauthRes = toJSON(errorRes{errors.ErrUnauthorizedAccess.Error()}) + unauthRes = toJSON(errorRes{errors.ErrAuthentication.Error()}) invalidRes = toJSON(errorRes{errors.ErrInvalidQueryParams.Error()}) ) diff --git a/consumers/notifiers/api/requests.go b/consumers/notifiers/api/requests.go index 8f9ecab8..6829123c 100644 --- a/consumers/notifiers/api/requests.go +++ b/consumers/notifiers/api/requests.go @@ -10,7 +10,6 @@ import ( var ( errInvalidTopic = errors.New("invalid Subscription topic") errInvalidContact = errors.New("invalid Subscription contact") - errNotFound = errors.New("invalid or empty Subscription id") ) type createSubReq struct { @@ -21,7 +20,7 @@ type createSubReq struct { func (req createSubReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.Topic == "" { return errInvalidTopic @@ -39,10 +38,10 @@ type subReq struct { func (req subReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { - return errNotFound + return errors.ErrNotFound } return nil } @@ -57,7 +56,7 @@ type listSubsReq struct { func (req listSubsReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil } diff --git a/consumers/notifiers/api/transport.go b/consumers/notifiers/api/transport.go index 2f73880f..322779f0 100644 --- a/consumers/notifiers/api/transport.go +++ b/consumers/notifiers/api/transport.go @@ -142,10 +142,9 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { errors.Contains(errorVal, errInvalidTopic), errors.Contains(errorVal, errors.ErrInvalidQueryParams): w.WriteHeader(http.StatusBadRequest) - case errors.Contains(errorVal, errors.ErrNotFound), - errors.Contains(errorVal, errNotFound): + case errors.Contains(errorVal, errors.ErrNotFound): w.WriteHeader(http.StatusNotFound) - case errors.Contains(errorVal, errors.ErrUnauthorizedAccess): + case errors.Contains(errorVal, errors.ErrAuthentication): w.WriteHeader(http.StatusUnauthorized) case errors.Contains(errorVal, errors.ErrConflict): w.WriteHeader(http.StatusConflict) diff --git a/consumers/notifiers/mocks/auth.go b/consumers/notifiers/mocks/auth.go index d918ecff..3d590098 100644 --- a/consumers/notifiers/mocks/auth.go +++ b/consumers/notifiers/mocks/auth.go @@ -27,7 +27,7 @@ func (svc authServiceMock) Identify(ctx context.Context, in *mainflux.Token, opt if id, ok := svc.users[in.Value]; ok { return &mainflux.UserIdentity{Id: id, Email: id}, nil } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { @@ -37,7 +37,7 @@ func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opt return &mainflux.Token{Value: id}, nil } } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc authServiceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { diff --git a/consumers/notifiers/service_test.go b/consumers/notifiers/service_test.go index df4225fc..879bc7b9 100644 --- a/consumers/notifiers/service_test.go +++ b/consumers/notifiers/service_test.go @@ -58,11 +58,11 @@ func TestCreateSubscription(t *testing.T) { err: errors.ErrConflict, }, { - desc: "test unauthorized access", + desc: "test with empty token", token: "", sub: notifiers.Subscription{Contact: exampleUser1, Topic: "valid.topic"}, id: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -103,11 +103,11 @@ func TestViewSubscription(t *testing.T) { err: errors.ErrNotFound, }, { - desc: "test unauthorized access", + desc: "test with empty token", token: "", id: id, sub: notifiers.Subscription{}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -178,7 +178,7 @@ func TestListSubscriptions(t *testing.T) { err: errors.ErrNotFound, }, { - desc: "test unauthorized access", + desc: "test with empty token", token: "", pageMeta: notifiers.PageMetadata{ Offset: 2, @@ -186,7 +186,7 @@ func TestListSubscriptions(t *testing.T) { Topic: "topic.subtopic.13", }, page: notifiers.Page{}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "test with topic", @@ -260,10 +260,10 @@ func TestRemoveSubscription(t *testing.T) { err: nil, }, { - desc: "test unauthorized access", + desc: "test with empty token", token: "", id: id, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } diff --git a/http/api/endpoint_test.go b/http/api/endpoint_test.go index 54f2b009..df77a6b6 100644 --- a/http/api/endpoint_test.go +++ b/http/api/endpoint_test.go @@ -89,7 +89,7 @@ func TestPublish(t *testing.T) { msg: msg, contentType: contentType, auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, "publish message with basic auth": { chanID: chanID, @@ -104,7 +104,7 @@ func TestPublish(t *testing.T) { msg: msg, contentType: contentType, auth: invalidToken, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, "publish message with invalid basic auth": { chanID: chanID, @@ -112,7 +112,7 @@ func TestPublish(t *testing.T) { contentType: contentType, auth: invalidToken, basicAuth: true, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, "publish message without content type": { chanID: chanID, diff --git a/http/api/transport.go b/http/api/transport.go index cf065667..392b152a 100644 --- a/http/api/transport.go +++ b/http/api/transport.go @@ -147,13 +147,13 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { switch err { case errMalformedData, errMalformedSubtopic: w.WriteHeader(http.StatusBadRequest) - case errors.ErrUnauthorizedAccess: - w.WriteHeader(http.StatusForbidden) + case errors.ErrAuthentication: + w.WriteHeader(http.StatusUnauthorized) default: if e, ok := status.FromError(err); ok { switch e.Code() { - case codes.PermissionDenied: - w.WriteHeader(http.StatusForbidden) + case codes.Unauthenticated: + w.WriteHeader(http.StatusUnauthorized) default: w.WriteHeader(http.StatusServiceUnavailable) } diff --git a/http/mocks/things.go b/http/mocks/things.go index 4e6236ae..a852b166 100644 --- a/http/mocks/things.go +++ b/http/mocks/things.go @@ -39,12 +39,12 @@ func (tc thingsClient) CanAccessByKey(ctx context.Context, req *mainflux.AccessB } if key == "" { - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } id, ok := tc.things[key] if !ok { - return nil, status.Error(codes.PermissionDenied, "invalid credentials provided") + return nil, status.Error(codes.Unauthenticated, "invalid credentials provided") } return &mainflux.ThingID{Value: id}, nil diff --git a/mqtt/handler.go b/mqtt/handler.go index 93285264..0f0477ec 100644 --- a/mqtt/handler.go +++ b/mqtt/handler.go @@ -65,7 +65,7 @@ func (h *handler) AuthConnect(c *session.Client) error { } if thid != c.Username { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if err := h.es.Connect(c.Username); err != nil { diff --git a/pkg/errors/types.go b/pkg/errors/types.go index 1ac5b456..9ca34792 100644 --- a/pkg/errors/types.go +++ b/pkg/errors/types.go @@ -4,8 +4,8 @@ package errors var ( - // ErrUnauthorizedAccess represents unauthorized access. - ErrUnauthorizedAccess = New("unauthorized access") + // ErrAuthentication indicates failure occurred while authenticating the entity. + ErrAuthentication = New("failed to perform authentication over the entity") // ErrAuthorization indicates failure occurred while authorizing the entity. ErrAuthorization = New("failed to perform authorization over the entity") diff --git a/pkg/sdk/go/certs.go b/pkg/sdk/go/certs.go index 31bc814d..e073d337 100644 --- a/pkg/sdk/go/certs.go +++ b/pkg/sdk/go/certs.go @@ -6,6 +6,8 @@ import ( "fmt" "io/ioutil" "net/http" + + "github.com/mainflux/mainflux/pkg/errors" ) const certsEndpoint = "certs" @@ -62,7 +64,7 @@ func (sdk mfSDK) RemoveCert(id, token string) error { case http.StatusNoContent: return nil case http.StatusForbidden: - return ErrUnauthorized + return errors.ErrAuthorization default: return ErrCertsRemove } diff --git a/pkg/sdk/go/message_test.go b/pkg/sdk/go/message_test.go index 10a39368..46e95c4f 100644 --- a/pkg/sdk/go/message_test.go +++ b/pkg/sdk/go/message_test.go @@ -61,13 +61,13 @@ func TestSendMessage(t *testing.T) { chanID: chanID, msg: msg, auth: "", - err: createError(sdk.ErrFailedPublish, http.StatusForbidden), + err: createError(sdk.ErrFailedPublish, http.StatusUnauthorized), }, "publish message with invalid authorization token": { chanID: chanID, msg: msg, auth: invalidToken, - err: createError(sdk.ErrFailedPublish, http.StatusForbidden), + err: createError(sdk.ErrFailedPublish, http.StatusUnauthorized), }, "publish message with wrong content type": { chanID: chanID, diff --git a/pkg/sdk/go/sdk.go b/pkg/sdk/go/sdk.go index 482476a0..ee196c49 100644 --- a/pkg/sdk/go/sdk.go +++ b/pkg/sdk/go/sdk.go @@ -24,9 +24,6 @@ const ( ) var ( - // ErrUnauthorized indicates that entity creation failed. - ErrUnauthorized = errors.New("unauthorized, missing credentials") - // ErrFailedCreation indicates that entity creation failed. ErrFailedCreation = errors.New("failed to create entity") diff --git a/pkg/sdk/go/users_test.go b/pkg/sdk/go/users_test.go index 3b5ed765..08eb3826 100644 --- a/pkg/sdk/go/users_test.go +++ b/pkg/sdk/go/users_test.go @@ -164,7 +164,7 @@ func TestCreateToken(t *testing.T) { desc: "create token for non existing user", user: sdk.User{Email: "user2@example.com", Password: "password"}, token: "", - err: createError(sdk.ErrFailedCreation, http.StatusForbidden), + err: createError(sdk.ErrFailedCreation, http.StatusUnauthorized), }, { desc: "create user with empty email", diff --git a/provision/api/requests.go b/provision/api/requests.go index 19291930..aacbd338 100644 --- a/provision/api/requests.go +++ b/provision/api/requests.go @@ -22,7 +22,7 @@ type mappingReq struct { func (req mappingReq) validate() error { if req.token == "" { - return errUnauthorized + return errors.ErrAuthentication } return nil } diff --git a/provision/api/transport.go b/provision/api/transport.go index e13db665..1231388b 100644 --- a/provision/api/transport.go +++ b/provision/api/transport.go @@ -18,11 +18,6 @@ const ( contentType = "application/json" ) -var ( - errUnauthorized = errors.New("missing or invalid credentials provided") - errConflict = errors.New("entity already exists") -) - // MakeHandler returns a HTTP handler for API endpoints. func MakeHandler(svc provision.Service) http.Handler { @@ -101,8 +96,10 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { w.WriteHeader(http.StatusUnsupportedMediaType) case io.EOF, errors.ErrMalformedEntity: w.WriteHeader(http.StatusBadRequest) - case errConflict: + case errors.ErrConflict: w.WriteHeader(http.StatusConflict) + case errors.ErrAuthentication: + w.WriteHeader(http.StatusUnauthorized) default: switch err.(type) { case *json.SyntaxError: diff --git a/provision/service.go b/provision/service.go index 75ff1586..076ea49f 100644 --- a/provision/service.go +++ b/provision/service.go @@ -250,7 +250,7 @@ func (ps *provisionService) Cert(token, thingID, ttl string, keyBits int) (strin th, err := ps.sdk.Thing(thingID, token) if err != nil { - return "", "", errors.Wrap(SDK.ErrUnauthorized, err) + return "", "", errors.Wrap(ErrUnauthorized, err) } cert, err := ps.sdk.IssueCert(th.ID, ps.conf.Cert.KeyBits, ps.conf.Cert.KeyType, ps.conf.Cert.TTL, token) return cert.ClientCert, cert.ClientKey, err diff --git a/readers/api/endpoint_test.go b/readers/api/endpoint_test.go index 10e95cb7..cbe712dc 100644 --- a/readers/api/endpoint_test.go +++ b/readers/api/endpoint_test.go @@ -185,7 +185,7 @@ func TestReadAll(t *testing.T) { desc: "read page with invalid token", url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID), token: invalid, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "read page with multiple offset", @@ -203,7 +203,7 @@ func TestReadAll(t *testing.T) { desc: "read page with empty token", url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID), token: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "read page with default offset", diff --git a/readers/api/transport.go b/readers/api/transport.go index 07452b67..a244e7bc 100644 --- a/readers/api/transport.go +++ b/readers/api/transport.go @@ -41,10 +41,7 @@ const ( defFormat = "messages" ) -var ( - errUnauthorizedAccess = errors.New("missing or invalid credentials provided") - auth mainflux.ThingsServiceClient -) +var auth mainflux.ThingsServiceClient // MakeHandler returns a HTTP handler for API endpoints. func MakeHandler(svc readers.MessageRepository, tc mainflux.ThingsServiceClient, svcName string) http.Handler { @@ -196,8 +193,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { case errors.Contains(err, nil): case errors.Contains(err, errors.ErrInvalidQueryParams): w.WriteHeader(http.StatusBadRequest) - case errors.Contains(err, errUnauthorizedAccess): - w.WriteHeader(http.StatusForbidden) + case errors.Contains(err, errors.ErrAuthentication): + w.WriteHeader(http.StatusUnauthorized) default: w.WriteHeader(http.StatusInternalServerError) } @@ -213,7 +210,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { func authorize(r *http.Request, chanID string) error { token := r.Header.Get("Authorization") if token == "" { - return errUnauthorizedAccess + return errors.ErrAuthentication } ctx, cancel := context.WithTimeout(context.Background(), time.Second) @@ -223,7 +220,7 @@ func authorize(r *http.Request, chanID string) error { if err != nil { e, ok := status.FromError(err) if ok && e.Code() == codes.PermissionDenied { - return errUnauthorizedAccess + return errors.ErrAuthorization } return err } diff --git a/readers/mocks/things.go b/readers/mocks/things.go index f73acef2..f9b668df 100644 --- a/readers/mocks/things.go +++ b/readers/mocks/things.go @@ -9,13 +9,10 @@ import ( "github.com/golang/protobuf/ptypes/empty" "github.com/mainflux/mainflux" + "github.com/mainflux/mainflux/pkg/errors" "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) -var errUnauthorized = status.Error(codes.PermissionDenied, "missing or invalid credentials provided") - var _ mainflux.ThingsServiceClient = (*thingsServiceMock)(nil) type thingsServiceMock struct{} @@ -28,11 +25,11 @@ func NewThingsService() mainflux.ThingsServiceClient { func (svc thingsServiceMock) CanAccessByKey(ctx context.Context, in *mainflux.AccessByKeyReq, opts ...grpc.CallOption) (*mainflux.ThingID, error) { token := in.GetToken() if token == "invalid" { - return nil, errUnauthorized + return nil, errors.ErrAuthentication } if token == "" { - return nil, errUnauthorized + return nil, errors.ErrAuthentication } return &mainflux.ThingID{Value: token}, nil diff --git a/things/api/auth/grpc/server.go b/things/api/auth/grpc/server.go index 38ec028b..94f627be 100644 --- a/things/api/auth/grpc/server.go +++ b/things/api/auth/grpc/server.go @@ -124,8 +124,10 @@ func encodeError(err error) error { return nil case errors.ErrMalformedEntity: return status.Error(codes.InvalidArgument, "received invalid can access request") - case errors.ErrUnauthorizedAccess: - return status.Error(codes.PermissionDenied, "missing or invalid credentials provided") + case errors.ErrAuthentication: + return status.Error(codes.Unauthenticated, "missing or invalid credentials provided") + case errors.ErrAuthorization: + return status.Error(codes.PermissionDenied, "unauthorized access token provided") case things.ErrEntityConnected: return status.Error(codes.PermissionDenied, "entities are not connected") case errors.ErrNotFound: diff --git a/things/api/auth/http/requests.go b/things/api/auth/http/requests.go index 3a70c31c..d252264e 100644 --- a/things/api/auth/http/requests.go +++ b/things/api/auth/http/requests.go @@ -11,7 +11,7 @@ type identifyReq struct { func (req identifyReq) validate() error { if req.Token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil @@ -24,7 +24,7 @@ type canAccessByKeyReq struct { func (req canAccessByKeyReq) validate() error { if req.Token == "" || req.chanID == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil @@ -37,7 +37,7 @@ type canAccessByIDReq struct { func (req canAccessByIDReq) validate() error { if req.ThingID == "" || req.chanID == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil diff --git a/things/api/auth/http/transport.go b/things/api/auth/http/transport.go index 6e672d6a..e08b3d0c 100644 --- a/things/api/auth/http/transport.go +++ b/things/api/auth/http/transport.go @@ -116,7 +116,7 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { w.Header().Set("Content-Type", contentType) switch err { - case errors.ErrUnauthorizedAccess: + case errors.ErrAuthentication: w.WriteHeader(http.StatusUnauthorized) case errors.ErrNotFound: w.WriteHeader(http.StatusNotFound) diff --git a/things/api/things/http/endpoint_test.go b/things/api/things/http/endpoint_test.go index 8b628234..b87b0ee9 100644 --- a/things/api/things/http/endpoint_test.go +++ b/things/api/things/http/endpoint_test.go @@ -52,7 +52,7 @@ var ( invalidName = strings.Repeat("m", maxNameSize+1) notFoundRes = toJSON(errorRes{errors.ErrNotFound.Error()}) unauthzRes = toJSON(errorRes{errors.ErrAuthorization.Error()}) - unauthRes = toJSON(errorRes{errors.ErrUnauthorizedAccess.Error()}) + unauthRes = toJSON(errorRes{errors.ErrAuthentication.Error()}) searchThingReq = things.PageMetadata{ Limit: 5, Offset: 0, diff --git a/things/api/things/http/requests.go b/things/api/things/http/requests.go index 13be4885..18fb4562 100644 --- a/things/api/things/http/requests.go +++ b/things/api/things/http/requests.go @@ -40,7 +40,7 @@ func validateUUID(extID string) (err error) { func (req createThingReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.ID != "" && validateUUID(req.ID) != nil { @@ -61,7 +61,7 @@ type createThingsReq struct { func (req createThingsReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if len(req.Things) <= 0 { @@ -90,7 +90,7 @@ type shareThingReq struct { func (req shareThingReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.thingID == "" || len(req.UserIDs) == 0 || len(req.Policies) == 0 { @@ -113,7 +113,7 @@ type updateThingReq struct { func (req updateThingReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -135,7 +135,7 @@ type updateKeyReq struct { func (req updateKeyReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" || req.Key == "" { @@ -154,7 +154,7 @@ type createChannelReq struct { func (req createChannelReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.ID != "" && validateUUID(req.ID) != nil { @@ -175,7 +175,7 @@ type createChannelsReq struct { func (req createChannelsReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if len(req.Channels) <= 0 { @@ -204,7 +204,7 @@ type updateChannelReq struct { func (req updateChannelReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -225,7 +225,7 @@ type viewResourceReq struct { func (req viewResourceReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -242,7 +242,7 @@ type listResourcesReq struct { func (req *listResourcesReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.pageMetadata.Limit == 0 { @@ -278,7 +278,7 @@ type listByConnectionReq struct { func (req listByConnectionReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -310,7 +310,7 @@ type connectThingReq struct { func (req connectThingReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.chanID == "" || req.thingID == "" { @@ -328,7 +328,7 @@ type connectReq struct { func (req connectReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if len(req.ChannelIDs) == 0 || len(req.ThingIDs) == 0 { @@ -357,7 +357,7 @@ type listThingsGroupReq struct { func (req listThingsGroupReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.groupID == "" { diff --git a/things/api/things/http/transport.go b/things/api/things/http/transport.go index 9c181fc3..62d28a1e 100644 --- a/things/api/things/http/transport.go +++ b/things/api/things/http/transport.go @@ -503,10 +503,9 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { case errors.Error: w.Header().Set("Content-Type", contentType) switch { - case errors.Contains(errorVal, errors.ErrUnauthorizedAccess), + case errors.Contains(errorVal, errors.ErrAuthentication), errors.Contains(errorVal, things.ErrEntityConnected): w.WriteHeader(http.StatusUnauthorized) - case errors.Contains(errorVal, errors.ErrAuthorization): w.WriteHeader(http.StatusForbidden) case errors.Contains(errorVal, errors.ErrInvalidQueryParams): diff --git a/things/mocks/auth.go b/things/mocks/auth.go index 74383983..258652c2 100644 --- a/things/mocks/auth.go +++ b/things/mocks/auth.go @@ -41,7 +41,7 @@ func (svc authServiceMock) Identify(ctx context.Context, in *mainflux.Token, opt if id, ok := svc.users[in.Value]; ok { return &mainflux.UserIdentity{Id: id, Email: id}, nil } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { @@ -51,7 +51,7 @@ func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opt return &mainflux.Token{Value: id}, nil } } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc authServiceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { diff --git a/things/redis/streams_test.go b/things/redis/streams_test.go index b5cea808..bfce4853 100644 --- a/things/redis/streams_test.go +++ b/things/redis/streams_test.go @@ -87,7 +87,7 @@ func TestCreateThings(t *testing.T) { desc: "create things with invalid credentials", ths: []things.Thing{{Name: "a", Metadata: map[string]interface{}{"test": "test"}}}, key: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, event: nil, }, } @@ -256,7 +256,7 @@ func TestRemoveThing(t *testing.T) { desc: "delete thing with invalid credentials", id: strconv.FormatUint(math.MaxUint64, 10), key: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, event: nil, }, } @@ -313,7 +313,7 @@ func TestCreateChannels(t *testing.T) { desc: "create channels with invalid credentials", chs: []things.Channel{{Name: "a", Metadata: map[string]interface{}{"test": "test"}}}, key: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, event: nil, }, } @@ -492,7 +492,7 @@ func TestRemoveChannel(t *testing.T) { desc: "create non-existent channel", id: strconv.FormatUint(math.MaxUint64, 10), key: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, event: nil, }, } diff --git a/things/service_test.go b/things/service_test.go index 2431cc28..f45768de 100644 --- a/things/service_test.go +++ b/things/service_test.go @@ -79,7 +79,7 @@ func TestCreateThings(t *testing.T) { desc: "create thing with wrong credentials", things: []things.Thing{{Name: "e"}}, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "create new things with external UUID", @@ -124,7 +124,7 @@ func TestUpdateThing(t *testing.T) { desc: "update thing with wrong credentials", thing: th, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "update non-existing thing", @@ -166,7 +166,7 @@ func TestUpdateKey(t *testing.T) { token: wrongValue, id: th.ID, key: key, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "update key of non-existing thing", @@ -220,7 +220,7 @@ func TestShareThing(t *testing.T) { thingID: th.ID, policies: policies, userIDs: []string{email2}, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "share a thing with partially invalid policies", @@ -258,7 +258,7 @@ func TestViewThing(t *testing.T) { "view thing with wrong credentials": { id: th.ID, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "view non-existing thing": { id: wrongID, @@ -347,7 +347,7 @@ func TestListThings(t *testing.T) { Limit: 0, }, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "list with metadata": { token: token, @@ -489,7 +489,7 @@ func TestListThingsByChannel(t *testing.T) { Limit: 0, }, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "list things by non-existent channel with wrong credentials": { token: token, @@ -591,7 +591,7 @@ func TestRemoveThing(t *testing.T) { desc: "remove thing with wrong credentials", id: sth.ID, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "remove existing thing", @@ -638,7 +638,7 @@ func TestCreateChannels(t *testing.T) { desc: "create channel with wrong credentials", channels: []things.Channel{{Name: "e"}}, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "create new channels with external UUID", @@ -683,7 +683,7 @@ func TestUpdateChannel(t *testing.T) { desc: "update channel with wrong credentials", channel: ch, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "update non-existing channel", @@ -719,7 +719,7 @@ func TestViewChannel(t *testing.T) { "view channel with wrong credentials": { id: ch.ID, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "view non-existing channel": { id: wrongID, @@ -813,7 +813,7 @@ func TestListChannels(t *testing.T) { Limit: 0, }, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "list with existing name": { token: token, @@ -976,7 +976,7 @@ func TestListChannelsByThing(t *testing.T) { Limit: 0, }, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "list channels by non-existent thing": { token: token, @@ -1078,7 +1078,7 @@ func TestRemoveChannel(t *testing.T) { desc: "remove channel with wrong credentials", id: ch.ID, token: wrongValue, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "remove existing channel", @@ -1135,7 +1135,7 @@ func TestConnect(t *testing.T) { token: wrongValue, chanID: ch.ID, thingID: th.ID, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "connect thing to non-existing channel", @@ -1197,7 +1197,7 @@ func TestDisconnect(t *testing.T) { token: wrongValue, chanID: ch.ID, thingID: th.ID, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "disconnect from non-existing channel", diff --git a/things/standalone/standalone.go b/things/standalone/standalone.go index 6b2bd45d..8af807ca 100644 --- a/things/standalone/standalone.go +++ b/things/standalone/standalone.go @@ -31,7 +31,7 @@ func NewAuthService(email, token string) mainflux.AuthServiceClient { func (repo singleUserRepo) Issue(ctx context.Context, req *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { if repo.token != req.GetEmail() { - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } return &mainflux.Token{Value: repo.token}, nil @@ -39,7 +39,7 @@ func (repo singleUserRepo) Issue(ctx context.Context, req *mainflux.IssueReq, op func (repo singleUserRepo) Identify(ctx context.Context, token *mainflux.Token, opts ...grpc.CallOption) (*mainflux.UserIdentity, error) { if repo.token != token.GetValue() { - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } return &mainflux.UserIdentity{Id: repo.email, Email: repo.email}, nil diff --git a/things/standalone/standalone_test.go b/things/standalone/standalone_test.go index c8ddf640..48ca5374 100644 --- a/things/standalone/standalone_test.go +++ b/things/standalone/standalone_test.go @@ -30,7 +30,7 @@ func TestIdentify(t *testing.T) { "identify non-existing user": { token: "non-existing", id: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "identify existing user": { token: token, @@ -54,10 +54,10 @@ func TestIssue(t *testing.T) { id string err error }{ - "issue key unauthorized": { + "issue key with an invalid token": { token: "non-existing", id: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "issue key": { token: token, diff --git a/twins/api/http/endpoint_states_test.go b/twins/api/http/endpoint_states_test.go index ac0a7aa9..20423c85 100644 --- a/twins/api/http/endpoint_states_test.go +++ b/twins/api/http/endpoint_states_test.go @@ -93,14 +93,14 @@ func TestListStates(t *testing.T) { { desc: "get a list of states with invalid token", auth: wrongValue, - status: http.StatusForbidden, + status: http.StatusUnauthorized, url: fmt.Sprintf(queryFmt, baseURL, 0, 5), res: nil, }, { desc: "get a list of states with empty token", auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, url: fmt.Sprintf(queryFmt, baseURL, 0, 5), res: nil, }, diff --git a/twins/api/http/endpoint_twins_test.go b/twins/api/http/endpoint_twins_test.go index c810adc5..74bd7374 100644 --- a/twins/api/http/endpoint_twins_test.go +++ b/twins/api/http/endpoint_twins_test.go @@ -138,7 +138,7 @@ func TestAddTwin(t *testing.T) { req: data, contentType: contentType, auth: wrongValue, - status: http.StatusForbidden, + status: http.StatusUnauthorized, location: "", }, { @@ -146,7 +146,7 @@ func TestAddTwin(t *testing.T) { req: data, contentType: contentType, auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, location: "", }, { @@ -253,20 +253,20 @@ func TestUpdateTwin(t *testing.T) { status: http.StatusNotFound, }, { - desc: "update twin with invalid user token", + desc: "update twin with invalid token", req: data, id: stw.ID, contentType: contentType, auth: wrongValue, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { - desc: "update twin with empty user token", + desc: "update twin with empty token", req: data, id: stw.ID, contentType: contentType, auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "update twin with invalid data format", @@ -359,7 +359,7 @@ func TestViewTwin(t *testing.T) { desc: "view twin by passing invalid token", id: stw.ID, auth: wrongValue, - status: http.StatusForbidden, + status: http.StatusUnauthorized, res: twinRes{}, }, { @@ -373,7 +373,7 @@ func TestViewTwin(t *testing.T) { desc: "view twin by passing empty token", id: stw.ID, auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, res: twinRes{}, }, } @@ -438,14 +438,14 @@ func TestListTwins(t *testing.T) { { desc: "get a list of twins with invalid token", auth: wrongValue, - status: http.StatusForbidden, + status: http.StatusUnauthorized, url: fmt.Sprintf(queryFmt, baseURL, 0, 1), res: nil, }, { desc: "get a list of twins with empty token", auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, url: fmt.Sprintf(queryFmt, baseURL, 0, 1), res: nil, }, @@ -608,13 +608,13 @@ func TestRemoveTwin(t *testing.T) { desc: "delete twin with invalid token", id: stw.ID, auth: wrongValue, - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, { desc: "delete twin with empty token", id: stw.ID, auth: "", - status: http.StatusForbidden, + status: http.StatusUnauthorized, }, } diff --git a/twins/api/http/requests.go b/twins/api/http/requests.go index 2db91bce..2230b80c 100644 --- a/twins/api/http/requests.go +++ b/twins/api/http/requests.go @@ -26,7 +26,7 @@ type addTwinReq struct { func (req addTwinReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if len(req.Name) > maxNameSize { @@ -46,7 +46,7 @@ type updateTwinReq struct { func (req updateTwinReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -67,7 +67,7 @@ type viewTwinReq struct { func (req viewTwinReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { @@ -87,7 +87,7 @@ type listReq struct { func (req *listReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.limit == 0 || req.limit > maxLimitSize { @@ -110,7 +110,7 @@ type listStatesReq struct { func (req *listStatesReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.id == "" { diff --git a/twins/api/http/transport.go b/twins/api/http/transport.go index aa0830fc..9af77c35 100644 --- a/twins/api/http/transport.go +++ b/twins/api/http/transport.go @@ -202,8 +202,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { switch err { case errors.ErrMalformedEntity: w.WriteHeader(http.StatusBadRequest) - case errors.ErrUnauthorizedAccess: - w.WriteHeader(http.StatusForbidden) + case errors.ErrAuthentication: + w.WriteHeader(http.StatusUnauthorized) case errors.ErrNotFound: w.WriteHeader(http.StatusNotFound) case errors.ErrConflict: diff --git a/twins/mocks/auth.go b/twins/mocks/auth.go index 5b889e28..3b015e07 100644 --- a/twins/mocks/auth.go +++ b/twins/mocks/auth.go @@ -31,7 +31,7 @@ func (svc authServiceClient) Identify(ctx context.Context, in *mainflux.Token, o if id, ok := svc.users[in.Value]; ok { return &mainflux.UserIdentity{Id: id, Email: id}, nil } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc *authServiceClient) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { diff --git a/twins/service.go b/twins/service.go index 3a07b417..0835e0b2 100644 --- a/twins/service.go +++ b/twins/service.go @@ -149,7 +149,7 @@ func (ts *twinsService) UpdateTwin(ctx context.Context, token string, twin Twin, _, err = ts.auth.Identify(ctx, &mainflux.Token{Value: token}) if err != nil { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } tw, err := ts.twins.RetrieveByID(ctx, twin.ID) @@ -218,7 +218,7 @@ func (ts *twinsService) RemoveTwin(ctx context.Context, token, twinID string) (e _, err = ts.auth.Identify(ctx, &mainflux.Token{Value: token}) if err != nil { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if err := ts.twins.Remove(ctx, twinID); err != nil { @@ -231,7 +231,7 @@ func (ts *twinsService) RemoveTwin(ctx context.Context, token, twinID string) (e func (ts *twinsService) ListTwins(ctx context.Context, token string, offset uint64, limit uint64, name string, metadata Metadata) (Page, error) { res, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) if err != nil { - return Page{}, errors.ErrUnauthorizedAccess + return Page{}, errors.ErrAuthentication } return ts.twins.RetrieveAll(ctx, res.GetEmail(), offset, limit, name, metadata) @@ -240,7 +240,7 @@ func (ts *twinsService) ListTwins(ctx context.Context, token string, offset uint func (ts *twinsService) ListStates(ctx context.Context, token string, offset uint64, limit uint64, twinID string) (StatesPage, error) { _, err := ts.auth.Identify(ctx, &mainflux.Token{Value: token}) if err != nil { - return StatesPage{}, errors.ErrUnauthorizedAccess + return StatesPage{}, errors.ErrAuthentication } return ts.states.RetrieveAll(ctx, offset, limit, twinID) diff --git a/twins/service_test.go b/twins/service_test.go index d08a9561..8b3ad0b1 100644 --- a/twins/service_test.go +++ b/twins/service_test.go @@ -52,7 +52,7 @@ func TestAddTwin(t *testing.T) { desc: "add twin with wrong credentials", twin: twin, token: wrongToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -90,7 +90,7 @@ func TestUpdateTwin(t *testing.T) { desc: "update twin with wrong credentials", twin: saved, token: wrongToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "update non-existing twin", @@ -126,7 +126,7 @@ func TestViewTwin(t *testing.T) { "view twin with wrong credentials": { id: saved.ID, token: wrongToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "view non-existing twin": { id: wrongID, @@ -187,7 +187,7 @@ func TestListTwins(t *testing.T) { token: wrongToken, limit: 0, offset: n, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -216,7 +216,7 @@ func TestRemoveTwin(t *testing.T) { desc: "remove twin with wrong credentials", id: saved.ID, token: wrongToken, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "remove existing twin", @@ -391,7 +391,7 @@ func TestListStates(t *testing.T) { offset: 0, limit: 10, size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, { desc: "get a list with id of non-existent twin", diff --git a/users/api/endpoint_test.go b/users/api/endpoint_test.go index d4c1ca8f..15f4cfbd 100644 --- a/users/api/endpoint_test.go +++ b/users/api/endpoint_test.go @@ -40,7 +40,7 @@ const ( var ( user = users.User{Email: validEmail, Password: validPass} notFoundRes = toJSON(errorRes{errors.ErrNotFound.Error()}) - unauthRes = toJSON(errorRes{errors.ErrUnauthorizedAccess.Error()}) + unauthRes = toJSON(errorRes{errors.ErrAuthentication.Error()}) malformedRes = toJSON(errorRes{errors.ErrMalformedEntity.Error()}) weakPassword = toJSON(errorRes{users.ErrPasswordFormat.Error()}) unsupportedRes = toJSON(errorRes{errors.ErrUnsupportedContentType.Error()}) @@ -104,10 +104,16 @@ func TestRegister(t *testing.T) { client := ts.Client() data := toJSON(user) + userNew := toJSON(users.User{Email: "user2@example.com", Password: "password"}) invalidData := toJSON(users.User{Email: invalidEmail, Password: validPass}) invalidPasswordData := toJSON(users.User{Email: validEmail, Password: invalidPass}) invalidFieldData := fmt.Sprintf(`{"email": "%s", "pass": "%s"}`, user.Email, user.Password) - unauthzEmail := "unauthz@example.com" + + mockAuthzDB := map[string][]mocks.SubjectSet{} + mockAuthzDB[user.Email] = append(mockAuthzDB[user.Email], mocks.SubjectSet{Object: authoritiesObjKey, Relation: memberRelationKey}) + auth := mocks.NewAuthService(map[string]string{user.Email: user.Email}, mockAuthzDB) + tkn, _ := auth.Issue(context.Background(), &mainflux.IssueReq{Id: user.ID, Email: user.Email, Type: 0}) + token := tkn.GetValue() cases := []struct { desc string @@ -116,18 +122,18 @@ func TestRegister(t *testing.T) { status int token string }{ - {"register new user", data, contentType, http.StatusCreated, user.Email}, - {"register user with empty token", data, contentType, http.StatusForbidden, ""}, - {"register existing user", data, contentType, http.StatusConflict, user.Email}, - {"register user with invalid email address", invalidData, contentType, http.StatusBadRequest, user.Email}, - {"register user with weak password", invalidPasswordData, contentType, http.StatusBadRequest, user.Email}, - {"register new user with unauthorized access", data, contentType, http.StatusForbidden, unauthzEmail}, - {"register existing user with unauthorized access", data, contentType, http.StatusForbidden, unauthzEmail}, - {"register user with invalid request format", "{", contentType, http.StatusBadRequest, user.Email}, - {"register user with empty JSON request", "{}", contentType, http.StatusBadRequest, user.Email}, - {"register user with empty request", "", contentType, http.StatusBadRequest, user.Email}, - {"register user with invalid field name", invalidFieldData, contentType, http.StatusBadRequest, user.Email}, - {"register user with missing content type", data, "", http.StatusUnsupportedMediaType, user.Email}, + {"register new user", data, contentType, http.StatusCreated, token}, + {"register user with empty token", data, contentType, http.StatusUnauthorized, ""}, + {"register existing user", data, contentType, http.StatusConflict, token}, + {"register user with invalid email address", invalidData, contentType, http.StatusBadRequest, token}, + {"register user with weak password", invalidPasswordData, contentType, http.StatusBadRequest, token}, + {"register new user with unauthenticated access", userNew, contentType, http.StatusUnauthorized, "wrong"}, + {"register existing user with unauthenticated access", data, contentType, http.StatusUnauthorized, "wrong"}, + {"register user with invalid request format", "{", contentType, http.StatusBadRequest, token}, + {"register user with empty JSON request", "{}", contentType, http.StatusBadRequest, token}, + {"register user with empty request", "", contentType, http.StatusBadRequest, token}, + {"register user with invalid field name", invalidFieldData, contentType, http.StatusBadRequest, token}, + {"register user with missing content type", data, "", http.StatusUnsupportedMediaType, token}, } for _, tc := range cases { @@ -182,9 +188,9 @@ func TestLogin(t *testing.T) { res string }{ {"login with valid credentials", data, contentType, http.StatusCreated, tokenData}, - {"login with invalid credentials", invalidData, contentType, http.StatusForbidden, unauthRes}, + {"login with invalid credentials", invalidData, contentType, http.StatusUnauthorized, unauthRes}, {"login with invalid email address", invalidEmailData, contentType, http.StatusBadRequest, malformedRes}, - {"login non-existent user", nonexistentData, contentType, http.StatusForbidden, unauthRes}, + {"login non-existent user", nonexistentData, contentType, http.StatusUnauthorized, unauthRes}, {"login with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes}, {"login with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes}, {"login with empty request", "", contentType, http.StatusBadRequest, malformedRes}, @@ -233,7 +239,7 @@ func TestUser(t *testing.T) { res string }{ {"user info with valid token", token, http.StatusOK, ""}, - {"user info with invalid token", "", http.StatusForbidden, ""}, + {"user info with invalid token", "", http.StatusUnauthorized, ""}, } for _, tc := range cases { @@ -366,7 +372,7 @@ func TestPasswordReset(t *testing.T) { tok string }{ {"password reset with valid token", reqExisting, contentType, http.StatusCreated, "{}", token}, - {"password reset with invalid token", reqNoExist, contentType, http.StatusForbidden, unauthRes, token}, + {"password reset with invalid token", reqNoExist, contentType, http.StatusUnauthorized, unauthRes, token}, {"password reset with confirm password not matching", reqPassNoMatch, contentType, http.StatusBadRequest, malformedRes, token}, {"password reset request with invalid request format", "{", contentType, http.StatusBadRequest, malformedRes, token}, {"password reset request with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes, token}, @@ -440,8 +446,8 @@ func TestPasswordChange(t *testing.T) { tok string }{ {"password change with valid token", dataResExisting, contentType, http.StatusCreated, "{}", token}, - {"password change with invalid token", reqNoExist, contentType, http.StatusForbidden, unauthRes, ""}, - {"password change with invalid old password", reqWrongPass, contentType, http.StatusForbidden, unauthRes, token}, + {"password change with invalid token", reqNoExist, contentType, http.StatusUnauthorized, unauthRes, ""}, + {"password change with invalid old password", reqWrongPass, contentType, http.StatusUnauthorized, unauthRes, token}, {"password change with invalid new password", reqWeakPass, contentType, http.StatusBadRequest, weakPassword, token}, {"password change with empty JSON request", "{}", contentType, http.StatusBadRequest, malformedRes, token}, {"password change empty request", "", contentType, http.StatusBadRequest, malformedRes, token}, diff --git a/users/api/requests.go b/users/api/requests.go index 3ed88930..106baa42 100644 --- a/users/api/requests.go +++ b/users/api/requests.go @@ -32,7 +32,7 @@ type viewUserReq struct { func (req viewUserReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil } @@ -47,7 +47,7 @@ type listUsersReq struct { func (req listUsersReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil } @@ -59,7 +59,7 @@ type updateUserReq struct { func (req updateUserReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil } @@ -103,7 +103,7 @@ type passwChangeReq struct { func (req passwChangeReq) validate() error { if req.Token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.OldPassword == "" { return errors.ErrMalformedEntity @@ -121,7 +121,7 @@ type listMemberGroupReq struct { func (req listMemberGroupReq) validate() error { if req.token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } if req.groupID == "" { diff --git a/users/api/transport.go b/users/api/transport.go index aee05926..f00f23f1 100644 --- a/users/api/transport.go +++ b/users/api/transport.go @@ -293,8 +293,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) { w.WriteHeader(http.StatusBadRequest) case errors.Contains(errorVal, errors.ErrMalformedEntity): w.WriteHeader(http.StatusBadRequest) - case errors.Contains(errorVal, errors.ErrUnauthorizedAccess): - w.WriteHeader(http.StatusForbidden) + case errors.Contains(errorVal, errors.ErrAuthentication): + w.WriteHeader(http.StatusUnauthorized) case errors.Contains(errorVal, errors.ErrAuthorization): w.WriteHeader(http.StatusForbidden) case errors.Contains(errorVal, errors.ErrConflict): diff --git a/users/mocks/authn.go b/users/mocks/authn.go index a891c724..2da336ac 100644 --- a/users/mocks/authn.go +++ b/users/mocks/authn.go @@ -37,7 +37,7 @@ func (svc authServiceMock) Identify(ctx context.Context, in *mainflux.Token, opt if id, ok := svc.users[in.Value]; ok { return &mainflux.UserIdentity{Id: id, Email: id}, nil } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opts ...grpc.CallOption) (*mainflux.Token, error) { @@ -47,7 +47,7 @@ func (svc authServiceMock) Issue(ctx context.Context, in *mainflux.IssueReq, opt return &mainflux.Token{Value: id}, nil } } - return nil, errors.ErrUnauthorizedAccess + return nil, errors.ErrAuthentication } func (svc authServiceMock) Authorize(ctx context.Context, req *mainflux.AuthorizeReq, _ ...grpc.CallOption) (r *mainflux.AuthorizeRes, err error) { diff --git a/users/mocks/hasher.go b/users/mocks/hasher.go index f3bd3491..9edfa5e9 100644 --- a/users/mocks/hasher.go +++ b/users/mocks/hasher.go @@ -27,7 +27,7 @@ func (hm *hasherMock) Hash(pwd string) (string, error) { func (hm *hasherMock) Compare(plain, hashed string) error { if plain != hashed { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } return nil diff --git a/users/service.go b/users/service.go index 3855a6e6..49af996e 100644 --- a/users/service.go +++ b/users/service.go @@ -158,7 +158,7 @@ func (svc usersService) checkAuthz(ctx context.Context, token string) error { return nil } if token == "" { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } ir, err := svc.identify(ctx, token) @@ -172,10 +172,10 @@ func (svc usersService) checkAuthz(ctx context.Context, token string) error { func (svc usersService) Login(ctx context.Context, user User) (string, error) { dbUser, err := svc.users.RetrieveByEmail(ctx, user.Email) if err != nil { - return "", errors.Wrap(errors.ErrUnauthorizedAccess, err) + return "", errors.Wrap(errors.ErrAuthentication, err) } if err := svc.hasher.Compare(user.Password, dbUser.Password); err != nil { - return "", errors.Wrap(errors.ErrUnauthorizedAccess, err) + return "", errors.Wrap(errors.ErrAuthentication, err) } return svc.issue(ctx, dbUser.ID, dbUser.Email, auth.LoginKey) } @@ -188,7 +188,7 @@ func (svc usersService) ViewUser(ctx context.Context, token, id string) (User, e dbUser, err := svc.users.RetrieveByID(ctx, id) if err != nil { - return User{}, errors.Wrap(errors.ErrUnauthorizedAccess, err) + return User{}, errors.Wrap(errors.ErrAuthentication, err) } return User{ @@ -207,7 +207,7 @@ func (svc usersService) ViewProfile(ctx context.Context, token string) (User, er dbUser, err := svc.users.RetrieveByEmail(ctx, ir.email) if err != nil { - return User{}, errors.Wrap(errors.ErrUnauthorizedAccess, err) + return User{}, errors.Wrap(errors.ErrAuthentication, err) } return User{ @@ -224,7 +224,7 @@ func (svc usersService) ListUsers(ctx context.Context, token string, offset, lim } if err := svc.authorize(ctx, id.id, "authorities", "member"); err != nil { - return UserPage{}, errors.Wrap(errors.ErrUnauthorizedAccess, err) + return UserPage{}, errors.Wrap(errors.ErrAuthentication, err) } return svc.users.RetrieveAll(ctx, offset, limit, nil, email, m) } @@ -256,7 +256,7 @@ func (svc usersService) GenerateResetToken(ctx context.Context, email, host stri func (svc usersService) ResetPassword(ctx context.Context, resetToken, password string) error { ir, err := svc.identify(ctx, resetToken) if err != nil { - return errors.Wrap(errors.ErrUnauthorizedAccess, err) + return errors.Wrap(errors.ErrAuthentication, err) } u, err := svc.users.RetrieveByEmail(ctx, ir.email) if err != nil { @@ -278,7 +278,7 @@ func (svc usersService) ResetPassword(ctx context.Context, resetToken, password func (svc usersService) ChangePassword(ctx context.Context, authToken, password, oldPassword string) error { ir, err := svc.identify(ctx, authToken) if err != nil { - return errors.Wrap(errors.ErrUnauthorizedAccess, err) + return errors.Wrap(errors.ErrAuthentication, err) } if !svc.passRegex.MatchString(password) { return ErrPasswordFormat @@ -288,7 +288,7 @@ func (svc usersService) ChangePassword(ctx context.Context, authToken, password, Password: oldPassword, } if _, err := svc.Login(ctx, u); err != nil { - return errors.ErrUnauthorizedAccess + return errors.ErrAuthentication } u, err = svc.users.RetrieveByEmail(ctx, ir.email) if err != nil || u.Email == "" { @@ -348,7 +348,7 @@ type userIdentity struct { func (svc usersService) identify(ctx context.Context, token string) (userIdentity, error) { identity, err := svc.auth.Identify(ctx, &mainflux.Token{Value: token}) if err != nil { - return userIdentity{}, errors.Wrap(errors.ErrUnauthorizedAccess, err) + return userIdentity{}, errors.Wrap(errors.ErrAuthentication, err) } return userIdentity{identity.Id, identity.Email}, nil diff --git a/users/service_test.go b/users/service_test.go index 55527f7d..a14167a8 100644 --- a/users/service_test.go +++ b/users/service_test.go @@ -114,18 +114,18 @@ func TestLogin(t *testing.T) { Email: wrong, Password: user.Password, }, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "login with wrong password": { user: users.User{ Email: user.Email, Password: wrong, }, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "login failed auth": { user: noAuthUser, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -158,17 +158,17 @@ func TestViewUser(t *testing.T) { userID: id, err: nil, }, - "view user with unauthorized token": { + "view user with empty token": { user: users.User{}, token: "", userID: id, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, - "view user with authorized token and invalid user id": { + "view user with valid token and invalid user id": { user: users.User{}, token: token, userID: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -202,7 +202,7 @@ func TestViewProfile(t *testing.T) { "invalid token's user info": { user: users.User{}, token: "", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -246,10 +246,10 @@ func TestListUsers(t *testing.T) { size: 0, err: nil, }, - "list user with unauthorized token": { + "list user with emtpy token": { token: "", size: 0, - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, "list users with offset and limit": { token: token, @@ -291,7 +291,7 @@ func TestUpdateUser(t *testing.T) { "update user with invalid token": { user: user, token: "non-existent", - err: errors.ErrUnauthorizedAccess, + err: errors.ErrAuthentication, }, } @@ -333,8 +333,8 @@ func TestChangePassword(t *testing.T) { err error }{ "valid user change password ": {token, "newpassword", user.Password, nil}, - "valid user change password with wrong password": {token, "newpassword", "wrongpassword", errors.ErrUnauthorizedAccess}, - "valid user change password invalid token": {"", "newpassword", user.Password, errors.ErrUnauthorizedAccess}, + "valid user change password with wrong password": {token, "newpassword", "wrongpassword", errors.ErrAuthentication}, + "valid user change password invalid token": {"", "newpassword", user.Password, errors.ErrAuthentication}, } for desc, tc := range cases { @@ -361,7 +361,7 @@ func TestResetPassword(t *testing.T) { err error }{ "valid user reset password ": {resetToken.GetValue(), user.Email, nil}, - "invalid user reset password ": {"", "newpassword", errors.ErrUnauthorizedAccess}, + "invalid user reset password ": {"", "newpassword", errors.ErrAuthentication}, } for desc, tc := range cases {