Beispiel #1
0
def login():
    claims = current_custom_claims()
    if not claims.get("is_login", False):
        return "", 401

    data = LoginSchema().load(request.get_json())

    email = claims["email"]
    credential_id = data["id"]

    authenticator = Authenticator.query.filter(
        Authenticator.credential_id == credential_id,
        Authenticator.user.has(email=email),
    ).first()

    if not authenticator:
        return {"error": "authenticator not found"}, 401

    webauthn_user = webauthn.WebAuthnUser(
        user_id=authenticator.user.id,
        username=authenticator.user.email,
        display_name=authenticator.user.name,
        icon_url=app.config["WEBAUTHN_ICON_URL"],
        credential_id=authenticator.credential_id,
        public_key=authenticator.public_key,
        sign_count=authenticator.sign_count,
        rp_id=app.config["WEBAUTHN_RP_ID"],
    )

    response = webauthn.WebAuthnAssertionResponse(
        webauthn_user=webauthn_user,
        challenge=claims["challenge"],
        assertion_response=data,
        origin=app.config["WEBAUTHN_ORIGIN"],
    )

    try:
        sign_count = response.verify()
    except Exception as exc:
        return {"error": str(exc)}, 401

    authenticator.sign_count = sign_count
    authenticator.last_used_at = datetime.now(timezone.utc)
    db.session.add(authenticator)
    db.session.commit()

    return (
        {
            "token": guard.encode_jwt_token(authenticator.user),
            "user": UserSchema().dump(authenticator.user),
            "authenticator": AuthenticatorSchema().dump(authenticator),
        },
        200,
    )
Beispiel #2
0
def protected():
    """
    A protected endpoint. The auth_required decorator will require a header
    containing a valid JWT
    .. example::
       $ curl http://localhost:5000/protected -X GET \
         -H "Authorization: Bearer <your_token>"
    """
    # TODO put these in their own function
    custom_claims = flask_praetorian.current_custom_claims()
    is_api_call = custom_claims.pop('is_api', False)
    message = ""
    if is_api_call:
        message = f"protected endpoint allowed: Token Store token_id is {flask_praetorian.current_token_id()}"
    else:
        message = "protected endpoint (allowed usr {})".format(
            flask_praetorian.current_user().username, )
    return flask.jsonify(message=message)
Beispiel #3
0
def protected_operator_accepted():
    """
    A protected endpoint that accepts any of the listed roles. The
    roles_accepted decorator will require that the supplied JWT includes at
    least one of the accepted roles
    .. example::
       $ curl http://localhost/protected_operator_accepted -X GET \
         -H "Authorization: Bearer <your_token>"
    """
    # TODO put these in their own function
    custom_claims = flask_praetorian.current_custom_claims()
    is_api_call = custom_claims.pop('is_api', False)
    message = ""
    if is_api_call:
        message = f" Token Store token_id is {flask_praetorian.current_token_id()}"
    else:
        message = "protected_operator_accepted endpoint (allowed usr {})".format(
            flask_praetorian.current_user().username, )
    return flask.jsonify(message=message)
Beispiel #4
0
def protected():
    """
    A protected endpoint. The auth_required decorator will require a header
    containing a valid JWT
    .. example::
       $ curl http://localhost:5000/protected -X GET \
         -H "Authorization: Bearer <your_token>"
    """
    custom_claims = flask_praetorian.current_custom_claims()
    firstname = custom_claims.pop('firstname', None)
    nickname = custom_claims.pop('nickname', None)
    surname = custom_claims.pop('surname', None)

    if nickname is None:
        user_string = "{} {}".format(firstname, surname)
    else:
        user_string = "{} '{}' {}".format(firstname, nickname, surname)

    return flask.jsonify(
        message="protected endpoint (allowed user {u})".format(
            u=user_string), )
Beispiel #5
0
def register():
    claims = current_custom_claims()
    if not claims.get("is_registration", False):
        return "", 401

    data = RegisterSchema().load(request.get_json())

    response = webauthn.WebAuthnRegistrationResponse(
        rp_id=app.config["WEBAUTHN_RP_ID"],
        origin=app.config["WEBAUTHN_ORIGIN"],
        registration_response=data,
        challenge=claims["challenge"],
        none_attestation_permitted=True,
    )

    try:
        credential = response.verify()
    except Exception as exc:
        return {"error": str(exc)}, 400

    user = User(
        id=UUID(current_user_id()), email=claims["email"], name=claims["name"],
    )

    authenticator = Authenticator(
        name=data["name"],
        credential_id=str(credential.credential_id, "utf-8"),
        public_key=str(credential.public_key, "utf-8"),
        sign_count=credential.sign_count,
    )

    user.authenticators = [authenticator]
    db.session.add(user)

    try:
        db.session.commit()
    except IntegrityError:
        return "", 409

    return "", 201
Beispiel #6
0
def protected_admin_required():
    """
    A protected endpoint that requires a role. The roles_required decorator
    will require that the supplied JWT includes the required roles
    .. example::
       $ curl http://localhost:5000/protected_admin_required -X GET \
          -H "Authorization: Bearer <your_token>"
    """

    #print(flask_praetorian.current_token().token_name)
    # TODO Fix this hack to get the jwt data and determine if it is a user or a token_store
    # TODO I added the function, get_jwt_data_from_app_context to be used by external programs
    jwt = flask_praetorian.get_jwt_data_from_app_context()
    print(type(jwt))
    roles = flask_praetorian.current_rolenames()
    print(roles)
    custom_claims = flask_praetorian.current_custom_claims()
    is_api_call = custom_claims.pop('is_api', False)
    print("is_api_call")
    return flask.jsonify(
        message=
        f"protected_admin_required endpoint (allowed token or user? {jwt})")