diff --git a/consent_provider/app.py b/consent_provider/app.py
index 65b29035eb2114ba8cff65695a3b09f6265903c6..0e17b7bb39634b711655f154ee978e84ec0bf856 100644
--- a/consent_provider/app.py
+++ b/consent_provider/app.py
@@ -1,91 +1,42 @@
-from flask import abort, Flask, redirect, render_template, request
+from flask import abort, Flask, redirect, request
 from flask.views import View
 from os import urandom, environ
 from hydra_client import HydraAdmin
-from flask_wtf import FlaskForm
-from wtforms import SubmitField, HiddenField
-from flask_wtf.csrf import CSRFProtect
-from wtforms.validators import DataRequired
-
+from db import User, BackendConnectionError
 
 HYDRA_ADMIN_URL = environ['HYDRA_ADMIN_URL']
 
-
-class ConsentForm(FlaskForm):
-    accept = SubmitField("accept")
-    challenge = HiddenField("challenge")
-
-
-class ConsentView(View):
-
-    methods = "GET", "POST"
-
-    def render_form(self, form, **context):
-        return render_template("consent.html", form=form, **context)
-
-    def dispatch_request(self):
-        hydra = HydraAdmin(HYDRA_ADMIN_URL)
-        form = ConsentForm()
-
-        challenge = request.args.get("consent_challenge") or form.challenge.data
-        if not challenge:
-            abort(400)
-
-        consent_request = hydra.consent_request(challenge)
-
-        session = {
-            "access_token": {},
-            "id_token": {
-                "sub": "248289761010",
-                "name": "Example User",
-                "given_name": "Example",
-                "family_name": "User",
-                "preferred_username": "example",
-                "email": "example@oas.example.com",
-                "picture": "",
-            },
-        }
-
-        if request.method == "GET":
-            return self.get(form, consent_request, session)
-        elif request.method == "POST":
-            return self.post(form, consent_request, session)
-        abort(405)
-
-    def get(self, form, consent_request, session):
-        if consent_request.skip:
-            redirect_to = consent_request.accept(
-                grant_scope=consent_request.requested_scope,
-                grant_access_token_audience=consent_request.requested_access_token_audience,
-                session=session,
-            )
-            return redirect(redirect_to)
-        else:
-            form.challenge.data = consent_request.challenge
-        return self.render_form(
-            form, user=consent_request.subject, client=consent_request.client
-        )
-
-    def post(self, form, consent_request, session):
-        if form.validate():
-            if form.accept.data:
-                redirect_to = consent_request.accept(
-                    grant_scope=consent_request.requested_scope,
-                    grant_access_token_audience=consent_request.requested_access_token_audience,
-                    session=session,
-                    remember=False
-                )
-            else:
-                redirect_to = consent_request.reject(error="user_decline")
-            return redirect(redirect_to)
-        else:
-            # TODO: show error message
-            pass
-        return self.render_form(form)
-
-
 app = Flask(__name__)
-app.secret_key = urandom(16)
-csrf = CSRFProtect(app)
 
-app.add_url_rule("/consent", view_func=ConsentView.as_view("consent"))
+@app.route('/', methods=['GET'])
+def home():
+    hydra = HydraAdmin(HYDRA_ADMIN_URL)
+    challenge = request.args.get("consent_challenge")
+    if not challenge:
+        abort(403)
+    consent_request = hydra.consent_request(challenge)
+    app_name = consent_request.client["client_name"]
+    username = consent_request.subject
+    try:
+        user = User(username)
+    except BackendConnectionError as error:
+        # TODO: replace with propper logging via logger
+        print("Retrieving user object from GraphQL server failed")
+        print(error)
+        return redirect(consent_request.reject(
+            "Permission denied",
+            error_description="Login request was denied due to an internal server error"))
+    access_granted = user.has_app_permission(app_name)
+    if access_granted:
+        session = user.get_oauth_session()
+        return redirect(consent_request.accept(
+            grant_scope=consent_request.requested_scope,
+            grant_access_token_audience=consent_request.requested_access_token_audience,
+            session=session,
+            ))
+    return redirect(consent_request.reject(
+        "Permission denied",
+        error_description="Login request was denied due to missing application permission"))
+
+if __name__ == '__main__':
+    app.run()
diff --git a/consent_provider/db.py b/consent_provider/db.py
new file mode 100644
index 0000000000000000000000000000000000000000..510833530e76e8b7f88aff875c219ae9fd09ff1d
--- /dev/null
+++ b/consent_provider/db.py
@@ -0,0 +1,76 @@
+from os import environ
+from hydra_client import HydraAdmin
+from graphqlclient import GraphQLClient
+import urllib
+import json
+
+GRAPHQL_URL = environ['GRAPHQL_URL']
+GRAPHQL_CLIENT = GraphQLClient(GRAPHQL_URL)
+
+
+class User():
+    def __init__(self, username):
+        self.username = username
+        try:
+            self._load_remote_user_info()
+        except urllib.error.HTTPError as error:
+            raise BackendConnectionError(
+                error.code,
+                error.headers,
+                ("Error during retrieval of userdata - " + error.reason))
+
+    def _load_remote_user_info(self):
+        querystring = '''{{
+        getUser(username: "{0}"){{
+            email,
+            applications{{
+                edges{{
+                    node{{
+                        name
+                    }}
+                }}
+            }}
+            }}}}'''.format(self.username)
+        result = json.loads(GRAPHQL_CLIENT.execute(querystring))
+        data = result["data"]["getUser"]
+        self.applications = list(map(lambda x: x["node"]["name"],
+                                     data["applications"]["edges"]))
+        self.email = data["email"]
+
+    def has_app_permission(self, appname):
+        return appname in self.applications
+
+    def get_oauth_session(self):
+        """Create openID Connect token
+
+        Use the userdata stored in the user object to create an OpenID Connect token.
+        The token will be passed to Hydra, which will store it and serve it to all OpenID Connect
+        Clients, that successfully query the /userinfo endpoint. Every field in the "id_token"
+        dictionary can be accessed through standard scopes and claims.
+        See https://openid.net/specs/openid-connect-core-1_0.html#Claims
+
+        Returns:
+            OpenID Connect token of type dict
+        """
+        return {
+            "access_token": {},
+            "id_token": {
+                "name": self.username,
+                "preferred_username": self.username,
+                "email" : self.email,
+                "picture": ""}
+        }
+
+
+class BackendConnectionError(Exception):
+    """Raised when requests to the backend server fail
+
+    Attributes:
+        code -- http response code
+        headers -- http response headers
+        reason -- reson for the error
+    """
+    def __init__(self, code, headers, reason):
+        self.code = code
+        self.headers = headers
+        self.reason = reason
diff --git a/consent_provider/requirements.txt b/consent_provider/requirements.txt
index 128d32e76b068d0d305215a9955361a7a7fc9e31..00c803983822201a1630f938960184bf1fa0d5c7 100644
--- a/consent_provider/requirements.txt
+++ b/consent_provider/requirements.txt
@@ -1,3 +1,3 @@
-Flask==1.1.1
-flask-wtf==0.14.2
-hydra-client==0.4.0
+Flask
+hydra-client
+graphqlclient
diff --git a/login_provider/Dockerfile b/login_provider/Dockerfile
index c671dd715c1d64a7ee2bf29f35b1881cffdbec30..cf821f60f279d4a14c866c3aff193b2b2cbeb8ea 100644
--- a/login_provider/Dockerfile
+++ b/login_provider/Dockerfile
@@ -12,7 +12,7 @@ EXPOSE 5000
 ENV FLASK_ENV production
 ENV FLASK_RUN_HOST 0.0.0.0
 ENV FLASK_RUN_PORT 5000
-ENV HYDRA_ADMIN_URL http://localhost:444
+ENV HYDRA_ADMIN_URL http://localhost:4445
 ENV GRAPHQL_URL http://localhost:5002/graphql
 
 CMD [ "flask", "run" ]
diff --git a/login_provider/requirements.txt b/login_provider/requirements.txt
index 72bf67b2748a4195946d5c65b55d2d79cc9c341e..082ed2567ec47d8a6dc7138ed1700975db7ccadc 100644
--- a/login_provider/requirements.txt
+++ b/login_provider/requirements.txt
@@ -1,6 +1,7 @@
-Flask==1.1.1
-flask-wtf==0.14.2
-hydra-client==0.4.0
-Flask-Security==3.0.0
-Flask-SQLAlchemy==2.4.0
-bcrypt==3.1.7
+Flask
+flask-wtf
+hydra-client
+Flask-Security
+Flask-SQLAlchemy
+bcrypt
+graphqlclient
diff --git a/login_provider/test/behave/features/login.feature b/login_provider/test/behave/features/login.feature
index f1279e92a6d2a34bbea0d4982038a3cf2f1b52b8..ca1ff06439cb4ebeb85646f99c8d9d0e03183b4a 100644
--- a/login_provider/test/behave/features/login.feature
+++ b/login_provider/test/behave/features/login.feature
@@ -25,6 +25,16 @@ Scenario: Logout and redirect to login screen
     Then I wait on element "input#username" for 1000ms to exist
     And I expect that element "input#password" does exist
 
+Scenario: Login with an invalid user
+    Given the element "input#username" is visible
+    And the element "input#password" is visible
+    And the element "input#submit" is visible
+    When I add "invalid_username" to the inputfield "input#username"
+    And I enter the "password" in the inputfield "input#password"
+    And I click on the button "input#submit"
+    Then I wait on element "input#logout" for 1000ms to not exist
+    And I expect that element "input#password" does exist
+
 Scenario: Login with an invalid password
     Given the element "input#username" is visible
     And the element "input#password" is visible