diff --git a/Pipfile b/Pipfile
index d1a67df51cdde9c86c390ea0b8a8228a527f87f8..b267e798ae199dd87a2bc82ceaa9ba415f846060 100644
--- a/Pipfile
+++ b/Pipfile
@@ -16,6 +16,8 @@ flask-jwt-extended = "*"
 marshmallow-enum = "*"
 storage = { git="git@gitlab.fi.muni.cz:grp-kontr2/kontr-storage-module.git", editable='true'  }
 gitpython = "*"
+flask-oauthlib = "*"
+pyopenssl = "*"
 
 
 [dev-packages]
@@ -24,4 +26,4 @@ gitpython = "*"
 
 [requires]
 
-python_version = "3.6"
\ No newline at end of file
+python_version = "3.6"
diff --git a/portal/__init__.py b/portal/__init__.py
index c1b11443a2d76a2948c83d2aee0da1f6daa4bca3..64509713c461c971378864de439af514e2996510 100644
--- a/portal/__init__.py
+++ b/portal/__init__.py
@@ -1,5 +1,6 @@
 from flask import Flask
 from flask_jwt_extended import JWTManager
+from flask_oauthlib.client import OAuth
 
 from portal.config import CONFIGURATIONS
 from flask_sqlalchemy import SQLAlchemy
@@ -9,6 +10,7 @@ from storage import Storage
 
 db = SQLAlchemy()
 jwt = JWTManager()
+oauth = OAuth()
 # TODO - urgent
 storage = Storage({
     "submissions_dir": "todo",
@@ -22,7 +24,7 @@ def config_app(flask_app):
     config_type = os.environ.get('PORTAL_CONFIG_TYPE', 'devel')
     config_object = CONFIGURATIONS[config_type]
     if config_object is None:
-        raise EnvironmentError()  # TODO some custom ex
+        raise RuntimeError()
     flask_app.config.from_object(config_object)
     # app.logger.removeHandler(default_handler) # from Flask release 1.0, not yet available
 
@@ -35,6 +37,9 @@ def create_app():
     db.init_app(app)
     # init the jwt
     jwt.init_app(app)
+    # init the oauth client
+    oauth.init_app(app)
     return app
 
+
 import portal.database.models
diff --git a/portal/rest/auth/gitlab.py b/portal/rest/auth/gitlab.py
new file mode 100644
index 0000000000000000000000000000000000000000..78be942fc2654745ee1658c3d7d29db4b2da5c6a
--- /dev/null
+++ b/portal/rest/auth/gitlab.py
@@ -0,0 +1,64 @@
+from flask import Blueprint, Flask, Config, url_for, request, redirect, session, jsonify, \
+    make_response
+from flask_oauthlib.client import OAuth, OAuthRemoteApp
+
+from portal import oauth
+
+
+def extract_user_info(me: dict):
+    return dict(
+        uco=None,  # TODO: Need from gitlab or prompt the user
+        name=me['name'],
+        username=me['username'],
+        email=me['email']
+    )
+
+
+def create_gitlab_app(oauth: OAuth) -> OAuthRemoteApp:
+    base_url = "https://gitlab.fi.muni.cz"
+    client_id = "323ee2a6e24291f899b8415bf6af2a0e89beed711de8a59e01a1291daecea330"
+    client_secret = "323ee2a6e24291f899b8415bf6af2a0e89beed711de8a59e01a1291daecea330"
+
+    return oauth.remote_app(
+        'gitlab',
+        base_url=base_url,
+        request_token_url=None,
+        access_token_url=base_url + "/oauth/token",
+        authorize_url=base_url + "/oauth/authorize",
+        access_token_method='POST',
+        consumer_key=client_id,
+        consumer_secret=client_secret
+    )
+
+
+gitlab = create_gitlab_app(oauth=oauth)
+oauth = Blueprint('oauth', __name__, url_prefix='/oauth')
+
+
+@oauth.route('/login', methods=['GET'])
+def oauth_login():
+    callback = url_for('oauth.oauth_authorized', _external=True, _scheme='https')
+    return gitlab.authorize(callback=callback)
+
+
+@oauth.route('/login/authorized', methods=['GET'])
+def oauth_authorized():
+    resp = gitlab.authorized_response()
+    if resp is None:
+        return 'Access denied: reason=%s error=%s' % (
+            request.args['error'],
+            request.args['error_description']
+        )
+
+    token = resp['access_token']
+    session['gitlab_token'] = (token, '')
+    me = gitlab.get('/api/v4/user')
+    user_info = extract_user_info(me)
+    data = dict(data=me.data, token=token)
+    return jsonify(data)
+
+
+@gitlab.tokengetter
+def get_gitlab_oauth_token():
+    token = session.get('gitlab_token')
+    return token
diff --git a/portal/service/errors.py b/portal/service/errors.py
index 72a4a3084ba95e62cd0c11e8463afdef41d17179..c2e4ee1a075f9b6754959a8acc194eeaa278ed90 100644
--- a/portal/service/errors.py
+++ b/portal/service/errors.py
@@ -6,6 +6,10 @@ class PortalError(RuntimeError):
     """
 
 
+class PortalConfigurationLoadError(PortalError):
+    pass
+
+
 class PortalAPIError(Exception):
     def __init__(self, code, message):
         self._code = code
diff --git a/run.py b/run.py
index e2ef812353912d5305577077ccf43dbfb1d27c76..be86174135155e0f3ce083fc7b846f8a5c11f500 100644
--- a/run.py
+++ b/run.py
@@ -1,5 +1,6 @@
 from portal import create_app
 from portal import db
+from portal.rest.auth.gitlab import oauth
 from portal.rest.auth.login import auth
 from sample_data.data_init import init_data
 
@@ -7,6 +8,8 @@ from portal.rest.courses.courses import courses
 from portal.rest.users.users import users
 from portal.rest.roles.roles import roles
 from portal.rest.groups.groups import groups
+from portal.rest.submissions.submissions import submissions
+from portal.rest.projects.projects import projects
 
 
 def init_db(app):
@@ -22,7 +25,10 @@ if __name__ == '__main__':
     app.register_blueprint(users)
     app.register_blueprint(roles)
     app.register_blueprint(groups)
+    app.register_blueprint(submissions)
+    app.register_blueprint(projects)
     app.register_blueprint(auth)
+    app.register_blueprint(oauth)
     # app.run(use_reloader=False)
     app.run()