📄User Registration

This page describes code related to user registration on Matar.


User Login

The user login for Matar app provides access_token() in form of JSON web tokens.

def simple_login():
    ret_val = errors = {}
    phone_number = request.json.get("phone_number")
    action = request.json.get("action")
    source = request.json.get("source")
    organization_id = request.json.get("organization_id") or DEFAULT_ORGANIZATION_ID
    organization = Organization.query.get(organization_id)
    if(not organization):
        return {"error": "no such organization"}, 400

    if(action == "send_otp"):
        UniqueEntry.create_send_otp(
            phone_number=phone_number,
            errors=errors
        )
        if(not errors):
            return {"message": "sent otp"}, 200
        return errors, 400

    elif(action == "submit_otp"):
        name = request.json.get("name")
        image_url = request.json.get("image_url")
        otp = request.json.get("otp")
        fcm_token = request.json.get("fcm_token") or request.headers.environ.get("HTTP_FCM_TOKEN")
        print("fcm token user", request.json.get("fcm_token"))
        UniqueEntry.submit_otp(
            phone_number=phone_number,
            otp=otp,
            errors=errors
        )
        if(errors):
            return errors, 400

        user = User.query.filter(User.phone_number == phone_number).first()
        if(not user):
            user = User(
                phone_number=phone_number,
                name=name,
                image_url=image_url,
                source=source,
                roles={"default": [organization_id]},
                fcm_token=fcm_token
            )
            user.commit()
        elif(fcm_token):
            user.fcm_token = fcm_token
            user.commit()

        ret_val["access_token"] = create_access_token(identity=user._id, fresh=True)
        ret_val["refresh_token"] = create_refresh_token(user._id)

        return ret_val, 200

Describing Code :

  • Starting the login flow ,user provides a phone numbers on which one-time verification otp (one-time password) is received via google firebase authentication.

  • Then a specified user name ,received otp and a token from FCM (call Firebase. messaging. token ) has to be submitted. FCM token is received everytime** the user opens the app **to ensure the device has the right token, then update the timestamp and optionally the token if it has changed.

  • Once all the details specified above are submitted an access and refresh token is generated via create_access_token() which is used to a make JSON web tokens. JSON Web Tokens(JWTs ) are a good way of securely transmitting information between client(app user) and server. JWTs are signed and uses public/private key pairs which ensure the senders are who they say they are.

  • It calls a function (UniqueEntry.submit_otp) to verify the OTP provided by the user. If there are errors, it returns an error response.It attempts to find a user with the specified phone_number. If the user does not exist, it creates a new user record with the provided details, including phone_number, name, image_url, source, and roles.


User Authentication

Here is a code snippet of how user authentication is protected with the functions below :

def authentication_required(func):
    @jwt_required()
    def inner(*args, **kwargs):
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        if(not user):
            return {"error": "no such user"}, 403
        return func(user=user, *args, **kwargs)
    inner.__name__ = func.__name__
    return inner

Describing Code :

  • When it comes to user authentication a JSON Web Token is used for authentication if valid you will be able to retrieve the authenticated user information using the get_jwt_identity() function .The jwt_required() is used to protect all the routes or app paths when required authorization.

  • The user object is fetched from a database using SQLAlchemy based on the user's identity (user_id) obtained from the JWT token.

    1. If a user with the given identity is not found in the database, it returns a JSON response indicating an error with a 403 (Forbidden) status code.

    2. If a user is found in the database, it calls the original function (func) with the user object as an argument and passes any additional arguments and keyword arguments. This allows the original function to access the authenticated user.

    3. Finally, it sets the __name__ attribute of the inner function to match the func function's name. This is done to preserve the name of the original function, which can be useful for debugging and introspection.

Last updated