User Authentication in flask
Tags: python, coding, tutorial, beginners
Published: 2023-10-16 02:06:08

## Intro
User authentication is used in many web applications. Companies like Google, Meta, Amazon, and other companies all use user authentication to keep track of user information such as Usernames, ID's, passwords, and many other things. It's important to learn user authentication for company projects or personal ones.

## How it works
User authentication is simply the process of identifying the user and accessing their information. Imagine a user entering a site like Facebook. They log in to their account then once they're in they can view all their personal information like posts, likes, and profile information. Then once they're done, they log out and cannot view their personal information until they log back in. While the user is browsing through Facebook user authentication happening in the background. At the start, the user is introduced to a login page where they first have to enter the correct information for their account. If the information is incorrect, Facebook cannot authenticate the user. Once the user enters the correct information Facebook logs them in their account, the application keeps the user's sensitive information until the user logs back out.

## Getting Started with login
The first thing we need is a view to handle the login route in our `backend`. We can make a class called that handles `POST` requests for `/login`:


```python
class Login(Resource):
    def post(self):
        username = request.get_json().get('username')
        password = request.get_json().get('password')

        user = User.query.filter_by(username=username).first()

        if user and user.authenticate(password):
            session['user_id'] = user.id
            return user.to_dict(), 200
        else:
            return {'error': 'Unauthorized'}, 401

api.add_resource(Login, '/login')
```

Let's break down the code. `class Login(Resource):` This code tells us that we are making a class called "Login" that inherits "Resource". Whenever a class inherits Resource it lets us know that the class will be handling HTTP requests. Next we have:
```python
def post(self):
      username = request.get_json().get('username')
      password = request.get_json().get('password')
```
This tells us that we will be using a `post` method and it gets JSON data that has `username` and `password` parameters. Lastly, we have the authentication part:
```python
        user = User.query.filter_by(username=username).first() 
        if user and user.authenticate(password):
            session['user_id'] = user.id
            return user.to_dict(), 200
        else:
            return {'error': 'Unauthorized'}, 401
```
We first look in our database and see if we can authenticate a user that has the `username` from the JSON data with this line of code: 
```python 
user = User.query.filter_by(username=username).first()
```
Then if we find that the `user` is in our database and the user's password matches, we set the session to the user's id and return the user's information along with a status code `200`. But if we cannot find the `user` we will return a JSON response with an `error` and a status code of `401`. To finish with our backend, we add 
```python
api.add_resource(Login, '/login')
```
This code means that if the user tries to access the endpoint `/login` it will run the class.

Now onto our frontend:
```REACT
function Login({ onLogin }) {
  const [username, setUsername] = useState("");

  function handleSubmit(e) {
    e.preventDefault();
    fetch("/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ username }),
    })
      .then((r) => r.json())
      .then((user) => onLogin(user));
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <button type="submit">Login</button>
    </form>
```
The `Login` component first creates a `username` state variable and a `setUsername` function to update the state. Next, we can take a look at the `handleSubmit(e)` function. First, we use `e.preventDefault();` to prevent the default behavior of the event. Then we can fetch our `/login` endpoint:
```REACT
   fetch("/login", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ username }),
  })
```
This code tells us that we will be making a POST request that expects the header `Content-Type` to be JSON data. Then the `body: JSON.stringify({ username })` converts the `username` state variable into JSON string. `.then((r) => r.json())` then parses the JSON data. Once the JSON is parsed, `.then((user) => onLogin(user));` calls the `onLogin` function prop with a `user` argument.
```REACT
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <button type="submit">Login</button>
    </form>
  );
```
Lastly, the `Login` function will return this form that takes in the `username` input and calls the `handleSubmit` function once the `<button type="submit">Login</button>` is pressed.

## How to stay logged in

To stay logged in we can make this simple route:
```python
class CheckSession(Resource):

    def get(self):
        user = User.query.filter(User.id == session.get('user_id')).first()
        if user:
            return user.to_dict()
        else:
            return {'message': '401: Not Authorized'}, 401

api.add_resource(CheckSession, '/check_session')
```
The `CheckSession` class is similar to the `Login` class we made in our backend except instead of defining a `post` method we will be defining a `get` method. We first look if the `user` is in our database then if we find the `user` we can either return a user dictionary or return a `message` that says  "Not Authorized" with a status code of `401` if the user was not found in the database.

## Finishing with logout

The last thing to do now is log out. When you've finished browsing through a website the last thing to do to keep others from accessing your information is to logout. We can log out by creating this route:
```python
class Logout(Resource):
    session['user_id'] = None
    return jsonify({'message': '204: No Content'}), 204

api.add_resource(Logout, '/logout')
```
As you can see it's very simple. This class sets the session's `user_id` to `None` and returns a `message` that says "No Content" and a status code of 204. This means that there will be no user in the current session. Now let's make the front end part:
```REACT
function Logout({ onLogout }) {
  function handleLogout() {
    fetch("/logout", {
      method: "DELETE",
    }).then(() => onLogout());
  }

  return (
    <header>
      <button onClick={handleLogout}>Logout</button>
    </header>
  );
}
```
This code is essentially the opposite of logging in. We first send a fetch request to the `/logout` endpoint with the method of `DELETE`. After the request is made we use `.then` and call the `onLogout` function prop. Lastly, we need to make a button that will call the `handleLogout` function and once this button is pressed the user will officially be logged out.

## Conclusion

To be a software developer, it is crucial to learn how User authentication works. It is used in many applications to protect users such as yourself from breaches of private and sensitive data as well as keep your information secure. By understanding how user authentication works, you have added one more skill to your arsenal as a software developer.

## Resources
{% embed https://www.techtarget.com/searchsecurity/definition/user-authentication %}
{% embed https://furry-shrimp-4f0.notion.site/Flask-Authentication-Cheatsheet-03cdb049e02a48a293e6481b9b5152a6 %}
Flatiron School Resources:
{% embed 
https://flatironschool.com/ %}