diff --git a/ExpressAPI/src/controllers/Session.ts b/ExpressAPI/src/controllers/Session.ts
new file mode 100644
index 0000000000000000000000000000000000000000..cb157695fed0d55fb83bd1af9ebd89564fb7ef5a
--- /dev/null
+++ b/ExpressAPI/src/controllers/Session.ts
@@ -0,0 +1,74 @@
+import { getReasonPhrase } from 'http-status-codes';
+import * as jwt            from 'jsonwebtoken';
+import { JwtPayload }      from 'jsonwebtoken';
+import Config              from '../config/Config';
+import express             from 'express';
+import ApiRequest          from '../models/ApiRequest';
+import User                from '../models/User';
+
+
+class Session {
+    private _profile: User = new User();
+
+    get profile(): User {
+        return this._profile;
+    }
+
+    set profile(newProfile: User) {
+        newProfile.currentSession = this;
+        this._profile = newProfile;
+    }
+
+    constructor(req: ApiRequest) {
+        const authorization = req.headers.authorization;
+        if ( authorization ) {
+            const jwtToken = authorization.replace('Bearer ', '');
+
+            try {
+                const jwtData = jwt.verify(jwtToken, Config.jwtSecretKey) as JwtPayload;
+
+                if ( jwtData.profile ) {
+                    this.profile.importFromJsonObject(jwtData.profile);
+                    this.profile.currentSession = this;
+                }
+            } catch ( err ) { }
+        }
+    }
+
+    private static getToken(profileJson: any): string {
+        return profileJson.id === null ? null : jwt.sign({ profile: profileJson }, Config.jwtSecretKey, { expiresIn: Config.sessionTimeout });
+    }
+
+    private async getResponse(code: number, data: any, descriptionOverride?: string): Promise<any> {
+        const profileJson = await this.profile.toJsonObject(false);
+
+        let reasonPhrase = '';
+
+        try {
+            reasonPhrase = getReasonPhrase(code);
+        } catch {}
+
+        return {
+            timestamp   : (new Date()).toISOString(),
+            code        : code,
+            description : descriptionOverride ? descriptionOverride : reasonPhrase,
+            sessionToken: Session.getToken(profileJson),
+            data        : data
+        };
+    }
+
+    /*
+     Send a response to the client
+     Information: Data could be a promise or an object. If it's a promise, we wait on the data to be resolved before sending the response
+     */
+    sendResponse(res: express.Response, code: number, data?: any, descriptionOverride?: string) {
+        Promise.resolve(data).then((toReturn: any) => {
+            this.getResponse(code, toReturn, descriptionOverride).then(response => {
+                res.status(code).json(response);
+            });
+        });
+    }
+}
+
+
+export default Session;