-1

EDIT:

This question has nothing to do with "will the browser work with a non-restful API" or "Token authorization headers". This question has to do with API-Design (look tags), Good practices and Authentication (/login), not Authorization (token header).

I know how to make an API, how HTTP protocol works, what is RPC and what is REST. If you read my question you might see that I understand the principles. Please read my question carefully. Dont just read the title itself and answer. You need context in order to answer.


I'm trying to design a REST API without using verbs. It's becoming more challenging, as I'm comfronting cases like Login/Authentication like controllers.

Like, how am I supposed to treat natural controllers like Authentication in a RESTful Service? I'm probably being too pedantic here, if I am please correct me, but if my API contains a request like

GET /authenticate

then it isn't considered fully restful by definition. Right? I mean, this is clearly a verb. Thus it's a RESTful+RPC API.

And if I break my REST principles for /authenticate then why should I not break my REST principles for other cases that make my life easier? Like some other business controllers for example:

GET /users (noun) REST
POST /register (verb) RPC
GET /logout (verb) RPC

This might seem like a very semantic issue, and if it does I would love you to tell me that I probably think of this in a stupid way, so I can stop caring about this. But it really seems strange to me to consider an API RESTfull when it clearly has verbs in it, so that's why I'm asking your opinion.

Otherwise, if there is a better more RESTful way to perform authentication, I would love some recommendations. As it was troublesome finding answers on the topic on Google, other than people saying "Dont use verbs in RESTful API", which is confusing in cases like this.

Disclaimer: (for not careful reviewers/readers)

This is probably not a duplicate of some other questions you might have seen, like this one How to create REST URLs without verbs?

I'm aware of what the correct solution is for this specific question, as OP asks something that can be very easily done by REST.

My issue is more semantic and not as much as a question over how to do basic REST operations like updating a user's field.

Neither this that I found is a duplicate but indeed very similar REST API Login Pattern The user asks which is an appropriate RESTful design, but he clearly does not get any answers that are answering what I'm asking. Which is the semantic (stupid or not) of "Is the design RESTful anymore if you have a /login path in your RESTful design". The answers are about Authorization, not Authentication.

Im forming this disclaimer because some of my past questions have been downvoted because they were considered duplicate, when they were actually just similar, and the downvotes were never removed even though I never got an answer back. Although, if you find an appropriate duplicate I would be really happy to accept it. Just please dont rudely throw a duplicate with the only duplicate thing being the title.

Eksapsy
  • 1,541
  • 3
  • 18
  • 26
  • What sort of authentication are you postulating? Put differently, why do you have an `/authenticate` endpoint? Why not just use `Authorization` on each resource and return 401 if it is wrong? If the `/authenticate` URL is to (for example) receive a login token to be used in later requests, then `GET /loginToken` with a `Authorization` header seems to fit the "restful" naming. This matches in idempotent thinking, too. – Mitch Oct 11 '19 at 22:50
  • (And if you are thinking that the `Authorization` header has anything to do with authorization, that is a misconception. The `Authorization` header carries the identity (authentication) of the client). I'll hold for response, but this seems a semantic duplicate for the linked question. – Mitch Oct 11 '19 at 22:53
  • Doesn't the user have to login somehow in order to get an `Authorization` header in the first place? Which means, that you actually have to include a `/login` or `/authonticate` endpoint? – Eksapsy Oct 11 '19 at 23:04
  • No. Not unless you want to. If your service is over https, using HTTP Basic is perfectly acceptable. If not, then that is typically the responsibility of a different (typically premade) service that will issue tokens. Resource endpoints just have to verify `Authorization` (either `basic` or `bearer`) and return a 401 when unhappy. Redirects+Cookies are possible, but a bit of an anti-pattern since it assumes an interactive user-agent. – Mitch Oct 12 '19 at 06:35
  • Thank you. But that still doesn't answer the question. How will the user get authorized in the first place with a *non-premade* (like Google/Twitter/Facebook) service. How am I supposed to have a login screen, without a `/login` API path and still be considered RESTful? – Eksapsy Oct 12 '19 at 09:31
  • Why would a REST API have a login screen? The client app may have a login screen, but the API wouldn't. If you are doing "local" UN/PW authentication then HTTP Basic is sufficient for your API as long as you run over HTTPS. The client app would start off in a "Not logged in" state, then collect credentials, then use the credentials to access resources - the first of which might be `/users/current` to find out what the display name and configuration is for a particular authentication. – Mitch Oct 12 '19 at 21:26
  • Correct, the client API will have the login screen. But in order for the login screen to work you need API to support that login screen's authentication. In order to login, you **must** contact with the API to get an authorization token if your username/password is correct, or otherwise to show that your authentication process failed. API requires a way to authenticate and then authorize him with the token client was given in successful Authentication. So, probably the answer is to have REST + RPC API together? Since I clearly can't have RESTful Authentication. – Eksapsy Oct 12 '19 at 21:48
  • 1
    You can use tokens if you want to, but they are not required. A token API would just be `GET /auth/token` - which is still resource oriented. A token API is just a tool for converting `Authorization: basic` (or some other authentication mechanism) into an `Authorization: bearer` header - there is no fundamental difference in architecture. (Other changes, yes. SSO, Claims, Two-factor, MITM mitigation when done correctly, but not typically API changes) – Mitch Oct 12 '19 at 21:53
  • @Mitch I thought that this method with the Basic auth does not either stores a session token (something like a bearer token) neither seems like a safe option (header forgery). So I searched more, and I found this answer https://stackoverflow.com/questions/4608225/how-do-i-implement-login-in-a-restful-web-service . I think it is perfectly similar to this one and has a great answer. What do you think. Its a great reason to mark this question as duplicate imo. – Eksapsy Oct 14 '19 at 21:37
  • But from what I see, there is a lot of complication and people fighting too in terms of what is considered RESTful and what is not. Really, the more I search about the topic, the more confused I get over what is good practice here. What a headache – Eksapsy Oct 14 '19 at 21:45

1 Answers1

0

An example REST client and server with local login would be:

Server API's:

  • GET /users/currentUser
    Returns a JSON document which describes the current user (display name, email address, theme preference, password expiration date, etc...)
    1. Validate username and password in Authorization: basic header, set context. If invalid, throw 401
    2. Retrieve user information, serialize, return
  • GET /todos/
    Returns a JSON document which contains all of the TODO items
    1. Validate username and password in Authorization: basic header, set context. If invalid, throw 401
    2. Retrieve To-Do items, serialize, return

Client:

  1. Start in "Unauthenticated" state, display login UI
  2. When login button is clicked, use username and password fields to compose a Authorization: basic header and add it to the HTTP client
  3. Make a test call to GET /users/currentUser with the header to validate login info and retrieve user information. If 401, login failed - return to login UI.
  4. Save the Authorization: basic header and transition to the "Authenticated" state, display app UI
  5. Make a call to GET /todos/, format and display. If a 401 occurs, transition to "Unauthenticated" state (e.g. password changed by other client)
Mitch
  • 21,223
  • 6
  • 63
  • 86