Skip to content

LiprikON2/Medods-Technical-Assessment

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Medods - Technical Assessment

Note

Используемые технологии:

  • Go
  • JWT
  • PostgreSQL
  • Docker

Задание

Написать часть сервиса аутентификации.

Два REST маршрута:

Первый маршрут выдает пару Access, Refresh токенов для пользователя с идентификатором (GUID) указанным в параметре запроса

POST http://localhost:8080/api/v1/auth/login/{GUID}

Пример запроса POST http://localhost:8080/api/v1/auth/login/cec24247-497f-48f2-8a93-4ccdc2fdd65b

Тело

(пусто)

Пример ответа

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2OTk5MTcsImlhdCI6MTczMzY5OTYxNywiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiMDBlMWFhNGMtN2YxMi00Y2Y4LWIyNGEtYmU1YTM2MjgyNTZjIn0.s9IfgsetfB1HzArmbAz3Rlh2Z4sGA5u2spcB3TT4Q9DFlDFLu9v7R-_kmHfeW1ugEwUnhpOQeja3FDNeHzuMIg",
  "refreshToken": "AOGqTH8STPiySr5aNiglbKwSAAE="
}

Реализация ./auth/internal/chi/authcontroller.go#L285

Второй маршрут выполняет Refresh операцию на пару Access, Refresh токенов

POST http://localhost:8080/api/v1/auth/refresh

Пример запроса POST http://localhost:8080/api/v1/auth/refresh

Тело

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2OTk5MTcsImlhdCI6MTczMzY5OTYxNywiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiMDBlMWFhNGMtN2YxMi00Y2Y4LWIyNGEtYmU1YTM2MjgyNTZjIn0.s9IfgsetfB1HzArmbAz3Rlh2Z4sGA5u2spcB3TT4Q9DFlDFLu9v7R-_kmHfeW1ugEwUnhpOQeja3FDNeHzuMIg",
  "refreshToken": "AOGqTH8STPiySr5aNiglbKwSAAE="
}

Пример ответа

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2OTk5ODIsImlhdCI6MTczMzY5OTY4MiwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiMDNjYzA2ZDMtNzc4OS00NjQ2LWIzNzYtOTU1NjU4NmFiNzcxIn0.Xx_9FPHK4nsUyS18F1t5bM56EbLPZ4tE_XWQtvMir6KEqm5GQKRgGoKuflZBJwfsNoKmzxGvEXYZvFGeykkZpQ",
  "refreshToken": "A8wG03eJRkazdpVWWGq3cawSAAE="
}

Реализация ./auth/internal/chi/authcontroller.go#L302

Требования

Access токен

  • Тип JWT
  • Aлгоритм SHA512
    • Для подписывания JWT токена используется алгоритм HMAC-SHA512
  • Хранить в базе строго запрещено

Refresh токен

  • Тип произвольный

  • Формат передачи base64

    • С учетом лимита на создание bcrypt хеша в 72 символа, максимальное количество байт которое сможет хранить в себе base64 строка (72 * 3/4) 54 байта
      • На идентификатор (UUID) уходит 16 байт
      • На IP адрес (netip.Addr) уходит используется 4 или 16 байт в зависимости от версии IPv4 или IPv6
    • Реализация ./auth/internal/jwt/jwtservice.go#L62
  • Хранится в базе исключительно в виде bcrypt хеша

    • Из факта соления через bcrypt следует, что при Refresh операции нельзя найти запись в бд исключительно по Refresh токену
      • Значит, нужно дополнительно хранить какой-нибудь идентификатор в Payload
    • Создание экземпляра для хранения в бд ./auth/internal/chi/authcontroller.go#L471
  • Должен быть защищен от изменения на стороне клиента

    • Из факта хеширования через bcrypt следует, что подписывать токен (как в JWT) не нужно - проверка целостности осуществляется через bcrypt
      • Во время Referesh операции bcrypt хеш передаваемого Refresh токена сравнивается с хешом в базе данных
  • Должен быть защищен от попыток повторного использования

    • У хранимых в базе данных Refresh токенов есть поле Active, на котором висит ограничение "у пользователя может быть только один активный токен"
      • Создание нового токена требует отзыва предыдущих
  • Access, Refresh токены обоюдно связаны, Refresh операцию для Access токена можно выполнить только тем Refresh токеном который был выдан вместе с ним

    • Во время Referesh операции у Access и Refresh токенов проверяется одинаковый ли у них jti
  • Payload токенов должен содержать сведения об ip адресе клиента, которому он был выдан

    • В обоих токенах есть поле для ip заполняемое по данным из chi/middleware RealIP
  • В случае, если ip адрес изменился, при рефреш операции нужно послать email warning на почту юзера (для упрощения можно использовать моковые данные)

Будет плюсом, если получится использовать Docker и покрыть код тестами.

Running

  1. Set up environment variables
cp .env.example .env
  1. Run docker-compose
docker-compose up --build

Developing

Installing uninstalled (but imported) dependencies

(cd auth && go mod tidy)

Testing

ref: https://go.dev/doc/code#Testing

Run all tests

(cd auth && go test ./...)

Architecture

Patterns:

  • DDD - Domain Driven Design
    • "Ensure that you solve valid problem in the optimal way. After that implement the solution in a way that your business will understand without any extra translation from technical language needed"
    • Applied to:
  • DIP - Dependency Inversion Principle
    • "D" in SOLID
      • "High-level modules should not depend on low-level modules. Both should depend on abstractions"
      • "Abstractions should not depend upon details. Details should depend upon abstractions"
    • Applied to:
  • CQRS - Command and Query Responsibility Segregation
    • "Every method should either be a command that performs an action, or a query that returns data to the caller, but not both"
    • Applied to:

Reference:


Endpoints

POST /api/v1/auth/register

Example request 1:

Body

{
  "email": "[email protected]",
  "password": "Hello1234!"
}

Example response:

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2OTkyMTQsImlhdCI6MTczMzY5ODkxNCwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiOTBmOWEwZTQtZDU1MC00MjM1LTg0ZTgtM2Q3YmQzNjAyODUwIn0.hbORB2206F0CIlsscxxtY1Pm1AQ2q4yQKghck7HBAjX7lCMUmjtxMKkXQgiLBrVToKWUmobMGs1wj1LLW13leg",
  "refreshToken": "kPmg5NVQQjWE6D1702AoUKwSAAE="
}
Example request 2:

Body

{
  "email": "[email protected]",
  "password": "hello1234"
}

Example response:

{
  "code": 422,
  "message": {
    "errors": [
      {
        "field": "password",
        "message": "password must contain at least one uppercase letter, one lowercase letter, one number, and one special character"
      }
    ]
  }
}
Example request 3:

Body

{
  "email": "[email protected]",
  "password": "Hello1234!"
}

Example response:

{
  "code": 409,
  "message": "user with this email already exists"
}
Example request 4:

Body

{
  "email": "[email protected]"
}

Example response:

{
  "code": 422,
  "message": {
    "errors": [
      {
        "field": "password",
        "message": "password is required"
      }
    ]
  }
}
Example request 5:

Body

{
  "hi": "hello"
}

Example response:

{
  "code": 400,
  "message": "json: unknown field \"hi\""
}
Example request 6:

Body

{
  "email": "[email protected]",
  "password": 1234568798
}

Example response:

{
  "code": 400,
  "message": "json: cannot unmarshal number into Go struct field CreateUserDto.password of type string"
}

POST /api/v1/auth/login

Example request 1:

Body

{
  "email": "[email protected]",
  "password": "Hello1234!"
}

Example response:

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzc4NTcsImlhdCI6MTczMzYzNzU1NywiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiMDgxNmIyMjctYjk5Ny00ZDQyLTlmY2MtNzUwMmU3MmRjZTRlIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.wXGy0c_iO1rw4XfZJwJpYg7cu6i1ZGKLqwr8GaRKgGC-V3Mntzan580ZNeurA0SW7LUl2770BaLmhRpy4wNf_A",
  "refreshToken": "CBayJ7mXTUKfzHUC5y3OTqwSAAE="
}
Example request 2:

Body

{
  "email": "[email protected]",
  "password": "wrongpass"
}

Example response:

{
  "code": 403,
  "message": "crypto/bcrypt: hashedPassword is not the hash of the given password"
}
Example request 3:

Body

{
  "email": "[email protected]",
  "password": "Hello1234!"
}

Example response:

{
  "code": 404,
  "message": "user with email [email protected] not found: sql: no rows in result set"
}

GET /api/v1/auth/me

  • Requires header Authorization: Bearer eyJhb...
Example request 1:

Headers

Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2OTk3NjUsImlhdCI6MTczMzY5OTQ2NSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiZDIwODA4ZWYtYWVlNS00MzI0LTg4ZTYtOGU5OTMyYjM3NmQ0In0.k4EnfkiENdBBk0SMvyjLLqgwgTyEc9YVg6dtyvmnX8A9YIk2-7SQPTzwLzPn3dPKUuVu-PxDa1ul9gq8emZ3LA

Example response:

{
  "uuid": "239a0eb8-ca36-4930-b087-81a1d6532005",
  "email": "[email protected]"
}
Example request 2:

Headers (bad accessToken)

Authorization: Bearer BADxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2OTk3NjUsImlhdCI6MTczMzY5OTQ2NSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiZDIwODA4ZWYtYWVlNS00MzI0LTg4ZTYtOGU5OTMyYjM3NmQ0In0.k4EnfkiENdBBk0SMvyjLLqgwgTyEc9YVg6dtyvmnX8A9YIk2-7SQPTzwLzPn3dPKUuVu-PxDa1ul9gq8emZ3LA

Example response:

{
  "code": 403,
  "message": "error verifying Authorization header: token signature is invalid: signature is invalid"
}

GET /api/v1/auth/

  • Requires header Authorization: Bearer eyJhb...
Example request 1:

Headers

Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2MzgwMjgsImlhdCI6MTczMzYzNzcyOCwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiZjk5YjkyNTMtNGIwYi00ZDFlLTg5NmUtOWVjYmMxNzJjNWUwIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.EYGs2uu7KXIwOJT_xf1bQ1xjxJvMrfhG0gwu67d89mZEJnvV7TWwyp3WmB3UOQSppRALkzxTV9fkdcpp19wEJw

Example response:

[
  {
    "email": "[email protected]"
  }
]
Example request 2:

Headers

(empty)

Example response:

{
  "code": 403,
  "message": "error verifying Authorization header: Authorization header must be provided"
}
Example request 2:

Headers (expired access token)

Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2MzgwMjgsImlhdCI6MTczMzYzNzcyOCwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiZjk5YjkyNTMtNGIwYi00ZDFlLTg5NmUtOWVjYmMxNzJjNWUwIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.EYGs2uu7KXIwOJT_xf1bQ1xjxJvMrfhG0gwu67d89mZEJnvV7TWwyp3WmB3UOQSppRALkzxTV9fkdcpp19wEJw

Example response:

{
  "code": 403,
  "message": "error verifying Authorization header: token has invalid claims: token is expired"
}

POST /api/v1/auth/login/{GUID}

Example request 1:

POST /api/v1/auth/login/898be767-f66f-494d-be9a-c1be85548bb7

Body

(empty)

Example response:

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg1NTIsImlhdCI6MTczMzYzODI1MiwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNzhkN2EwNTEtYjU0ZS00NDczLWI5MTEtYjE0YzIwZjI5OGJjIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.9Y7pkxA0iTsp2XX8sbDh3oBtHOPbFTztet-QsMTUkH4mlE3MGjqTekoiqtAphXKEjBN-EIbKJqLeZI5wa6uKtw",
  "refreshToken": "eNegUbVORHO5EbFMIPKYvKwSAAE="
}
Example request 2:

POST /api/v1/auth/login/malformed-f66f-494d-be9a-c1be85548bb7

Body

(empty)

Example response:

{
  "code": 400,
  "message": "invalid UUID format: invalid UUID length: 37"
}
Example request 3:

POST /api/v1/auth/login/00000000-f66f-494d-be9a-c1be85548bb7

Body

(empty)

Example response:

{
  "code": 404,
  "message": "user not found: sql: no rows in result set"
}

POST /api/v1/auth/refresh

Example request 1:

Body

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg3MTUsImlhdCI6MTczMzYzODQxNSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNTI3NTdlNjQtMDlkNi00MWI5LTg4YjgtZjFkMDljNzRhN2IyIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.g7Zl5_MXMN3IyURgR3VIHjgZZrq1o6YEp3odrSsoQV8YDBj2iqhxEHOkcdRVQsai1xjH53f5pyw1867CQQf4Lg",
  "refreshToken": "UnV+ZAnWQbmIuPHQnHSnsqwSAAE="
}

Example response:

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg3NDUsImlhdCI6MTczMzYzODQ0NSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiZmY5N2FlNjMtZjdjMC00NTAyLWIwYmEtNzY4YjAyNmI5N2I3Iiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.4zNEUcQCt0FR03se6x0UN_hYVqRrvBKtjCwGj6OI-k1glfSFdpRfripXFAshNI6RyH07hhZOVNB7oEBJwZH-hg",
  "refreshToken": "/5euY/fARQKwunaLAmuXt6wSAAE="
}
Example request 2:

Body (missing refreshToken)

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg3MTUsImlhdCI6MTczMzYzODQxNSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNTI3NTdlNjQtMDlkNi00MWI5LTg4YjgtZjFkMDljNzRhN2IyIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.g7Zl5_MXMN3IyURgR3VIHjgZZrq1o6YEp3odrSsoQV8YDBj2iqhxEHOkcdRVQsai1xjH53f5pyw1867CQQf4Lg"
}

Example response:

{
  "code": 403,
  "message": "crypto/bcrypt: hashedPassword is not the hash of the given password"
}
Example request 3:

Body (missing accessToken)

{
  "refreshToken": "UnV+ZAnWQbmIuPHQnHSnsqwSAAE="
}

Example response:

{
  "code": 400,
  "message": "token is malformed: token contains an invalid number of segments"
}
Example request 4:

Body (bad accessToken)

{
  "accessToken": "badhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg4NTMsImlhdCI6MTczMzYzODU1MywiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiN2IxMDFkNDAtZDZhOC00OTNkLWE3NjMtYzNjNjlmYjQ5YTdhIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.U-TDrcRpRzMoao3gB6D8lLiOKnZf81ZLGUx1NLRNI7TNgyimaYXUftu7NMdPMGqaN3VmCHQsY6LXptoBUASBaQ",
  "refreshToken": "exAdQNaoST2nY8PGn7SaeqwSAAE="
}

Example response:

{
  "code": 400,
  "message": "token is malformed: could not JSON decode header: invalid character 'm' looking for beginning of value"
}
Example request 5:

Body (bad refreshToken)

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg4NTMsImlhdCI6MTczMzYzODU1MywiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiN2IxMDFkNDAtZDZhOC00OTNkLWE3NjMtYzNjNjlmYjQ5YTdhIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.U-TDrcRpRzMoao3gB6D8lLiOKnZf81ZLGUx1NLRNI7TNgyimaYXUftu7NMdPMGqaN3VmCHQsY6LXptoBUASBaQ",
  "refreshToken": "baddQNaoST2nY8PGn7SaeqwSAAE="
}

Example response:

{
  "code": 403,
  "message": "crypto/bcrypt: hashedPassword is not the hash of the given password"
}
Example request 6:

Body (revoked refreshToken)

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg5NDEsImlhdCI6MTczMzYzODY0MSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNjVhMmIwNzQtMjk2NC00OWZkLWE0ZmQtZWUyM2ZhZTNmMWIzIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.YNJVAB7ICxTrTvxCu06OuJiGZLjhyGdOduoYzWmdRLYpzuoxh1kAt8Y-iIYxoYqVPmFHMqWTTpFB7Bfix_HXdA",
  "refreshToken": "ZaKwdClkSf2k/e4j+uPxs6wSAAE="
}

Example response:

{
  "code": 403,
  "message": "crypto/bcrypt: hashedPassword is not the hash of the given password"
}
Example request 7:

Body (new refreshToken with old accessToken)

{
  "accessToken": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2Mzg5ODMsImlhdCI6MTczMzYzODY4MywiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNGJjZWU0NjYtZTcxNC00NzE2LWFkODMtNjQyN2RhZmMwZGFmIiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.0uyY8_Zc2oCXQPspeDE88zo2u5AIL0pbroqpT5niTvONnu6xGjt-ZNXXCmBqfvR86WxGcPp2IdAcKj5TsDpGbA",
  "refreshToken": "HGYsNpzcS4iLfmhamWjdqKwSAAE="
}

Example response:

{
  "code": 403,
  "message": "jti in accessToken and refreshToken do not match"
}

GET /api/v1/auth/{GUID}

Example request 1:

GET /api/v1/auth/898be767-f66f-494d-be9a-c1be85548bb7

Example response:

{
  "email": "[email protected]"
}
Example request 2:

GET /api/v1/auth/badbe767-f66f-494d-be9a-c1be85548bb7

Example response:

{
  "code": 404,
  "message": "user not found: sql: no rows in result set"
}

PATCH /api/v1/auth/{GUID}

  • Requires header Authorization: Bearer eyJhb...
Example request 1:

Body

{
  "email": "[email protected]",
  "password": "NewPass123!"
}

Example response:

{
  "uuid": "898be767-f66f-494d-be9a-c1be85548bb7",
  "email": "[email protected]"
}
Example request 2:

Body

{
  "email": "[email protected]"
}

Example response:

{
  "uuid": "898be767-f66f-494d-be9a-c1be85548bb7",
  "email": "[email protected]"
}
Example request 3:

Body

{
  "uuid": "000000-f66f-494d-be9a-c1be85548bb7",
  "email": "[email protected]"
}

Example response:

{
  "code": 400,
  "message": "json: unknown field \"uuid\""
}
Example request 4:

Body

{}

Example response:

{
  "uuid": "898be767-f66f-494d-be9a-c1be85548bb7",
  "email": "[email protected]"
}
Example request 5:

Body

{
  "email": "bad_new_email",
  "password": "bad_new_pass"
}

Example response:

{
  "code": 422,
  "message": {
    "errors": [
      {
        "field": "email",
        "message": "invalid email format"
      },
      {
        "field": "password",
        "message": "password must contain at least one uppercase letter, one lowercase letter, one number, and one special character"
      }
    ]
  }
}

DELETE /api/v1/auth/{GUID}

  • Requires header Authorization: Bearer eyJhb...
Example request 1:

DELETE http://localhost:8080/api/v1/auth/898be767-f66f-494d-be9a-c1be85548bb7

Headers

Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2MzkzMDUsImlhdCI6MTczMzYzOTAwNSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNjQyNThmZjgtYmFmNC00OTQ4LTliNWMtNTVjNTExOWEyZjI3Iiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.t3GeawGNFsRBiPRzD6OU8ZQAWm66ZgO-kNXdMeistDnng3nAohw1qV_Gmdtjj8Wb4Z_8vgRzy2FdvVBz48NKYg

Example response (204):

(empty)
Example request 2:

DELETE http://localhost:8080/api/v1/auth/898be767-f66f-494d-be9a-c1be85548bb7

Headers

(empty)

Example response:

{
  "code": 403,
  "message": "error verifying Authorization header: token is malformed: token contains an invalid number of segments"
}
Example request 3:

DELETE http://localhost:8080/api/v1/auth/898be767-f66f-494d-be9a-c1be85548bb7

Headers (expired token)

Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2MzkzMDUsImlhdCI6MTczMzYzOTAwNSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNjQyNThmZjgtYmFmNC00OTQ4LTliNWMtNTVjNTExOWEyZjI3Iiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.t3GeawGNFsRBiPRzD6OU8ZQAWm66ZgO-kNXdMeistDnng3nAohw1qV_Gmdtjj8Wb4Z_8vgRzy2FdvVBz48NKYg

Example response:

{
  "code": 403,
  "message": "error verifying Authorization header: token has invalid claims: token is expired"
}
Example request 4:

DELETE http://localhost:8080/api/v1/auth/00000000-f66f-494d-be9a-c1be85548bb7

Headers (expired token)

Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MzM2MzkzMDUsImlhdCI6MTczMzYzOTAwNSwiaXAiOiIxNzIuMTguMC4xIiwianRpIjoiNjQyNThmZjgtYmFmNC00OTQ4LTliNWMtNTVjNTExOWEyZjI3Iiwic3ViIjoiODk4YmU3NjctZjY2Zi00OTRkLWJlOWEtYzFiZTg1NTQ4YmI3In0.t3GeawGNFsRBiPRzD6OU8ZQAWm66ZgO-kNXdMeistDnng3nAohw1qV_Gmdtjj8Wb4Z_8vgRzy2FdvVBz48NKYg

Example response:

{
  "code": 404,
  "message": "error deleting user: user not found"
}

About

BACKEND - Technical assessment for Medods

Resources

Stars

Watchers

Forks

Languages