diff --git a/studyguides/apps/auth/__init__.py b/studyguides/apps/auth/__init__.py
index e69de29..26c40ff 100644
--- a/studyguides/apps/auth/__init__.py
+++ b/studyguides/apps/auth/__init__.py
@@ -0,0 +1 @@
+default_app_config = "studyguides.apps.auth.apps.AuthConfig"
diff --git a/studyguides/apps/auth/admin.py b/studyguides/apps/auth/admin.py
deleted file mode 100644
index 8c38f3f..0000000
--- a/studyguides/apps/auth/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/studyguides/apps/auth/models.py b/studyguides/apps/auth/models.py
deleted file mode 100644
index 71a8362..0000000
--- a/studyguides/apps/auth/models.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.db import models
-
-# Create your models here.
diff --git a/studyguides/apps/auth/oauth.py b/studyguides/apps/auth/oauth.py
index eafd17b..f797ba1 100644
--- a/studyguides/apps/auth/oauth.py
+++ b/studyguides/apps/auth/oauth.py
@@ -1,40 +1,36 @@
+from typing import Any, Dict, List
+
 from social_core.backends.oauth import BaseOAuth2
 from social_core.pipeline.user import get_username as social_get_username
 
 
-def get_username(strategy, details, user = None, *args, **kwargs):
-    result = social_get_username(strategy, details, user = user, *args, **kwargs)
+def get_username(strategy, details, *args, user=None, **kwargs):
+    result = social_get_username(strategy, details, user=user, *args, **kwargs)
     return result
 
 
 class IonOauth2(BaseOAuth2):
-    name = 'ion'
-    AUTHORIZATION_URL = 'https://ion.tjhsst.edu/oauth/authorize'
-    ACCESS_TOKEN_URL = 'https://ion.tjhsst.edu/oauth/token'
-    ACCESS_TOKEN_METHOD = 'POST'
-    EXTRA_DATA = [
-        ('refresh_token', 'refresh_token', True),
-        ('expires_in', 'expires')
-    ]
+    name = "ion"
+    AUTHORIZATION_URL = "https://ion.tjhsst.edu/oauth/authorize"
+    ACCESS_TOKEN_URL = "https://ion.tjhsst.edu/oauth/token"
+    ACCESS_TOKEN_METHOD = "POST"
+    EXTRA_DATA = [("refresh_token", "refresh_token", True), ("expires_in", "expires")]
 
-    def get_scope(self):
+    def get_scope(self) -> List[str]:
         return ["read"]
 
-    def get_user_details(self, response):
+    def get_user_details(self, response: Dict[str, Any]) -> Dict[str, Any]:
         profile = self.get_json(
-            'https://ion.tjhsst.edu/api/profile',
-            params = {'access_token': response['access_token']},
+            "https://ion.tjhsst.edu/api/profile", params={"access_token": response["access_token"]},
         )
         # fields used to populate/update User model
-        return {
-            'id': profile['id'],
-            'username': profile['ion_username'],
-            'first_name': profile['first_name'],
-            'last_name': profile['last_name'],
-            'full_name': profile['full_name'],
-            'email': profile['tj_email'],
+        data = {
+            key: profile[key]
+            for key in ("first_name", "last_name", "id", "is_student", "is_teacher")
         }
+        data["username"] = profile["ion_username"]
+        data["email"] = profile["tj_email"]
+        return data
 
-    def get_user_id(self, details, response):
-        return details["id"]
-
+    def get_user_id(self, details: Dict[str, Any], response: Any) -> int:
+        return details["id"]
\ No newline at end of file
diff --git a/studyguides/apps/auth/urls.py b/studyguides/apps/auth/urls.py
index af37471..103f9c0 100644
--- a/studyguides/apps/auth/urls.py
+++ b/studyguides/apps/auth/urls.py
@@ -5,7 +5,7 @@ from . import views
 app_name = "auth"
 
 urlpatterns = [
-    path("login", views.login, name = "login"),
-    path("logout", views.logout, name = "logout"),
+    path("", views.index, name="index"),
+    path("login/", views.login, name="login"),
 ]
 
diff --git a/studyguides/apps/auth/views.py b/studyguides/apps/auth/views.py
index def013a..44d23ff 100644
--- a/studyguides/apps/auth/views.py
+++ b/studyguides/apps/auth/views.py
@@ -1,10 +1,10 @@
-from django.shortcuts import render
-from django.contrib.auth.views import LogoutView
+from django.shortcuts import redirect, render
 
-# Create your views here.
+def index(request):
+    if request.user.is_authenticated:
+        return redirect("home:index")
+    else:
+        return redirect("auth:login")
 
 def login(request):
-    return render(request, "auth/login.html")
-
-logout = LogoutView.as_view()
-
+    return render(request, "login.html")
diff --git a/studyguides/apps/courses/urls.py b/studyguides/apps/courses/urls.py
index 78b6085..3cace70 100644
--- a/studyguides/apps/courses/urls.py
+++ b/studyguides/apps/courses/urls.py
@@ -5,7 +5,7 @@ from . import views
 app_name = "courses"
 
 urlpatterns = [
-    path("<str:subject_url>/", views.subject_view),
+    path("subject/<str:subject_url>/", views.subject_view),
     path("tag/<str:tag>/", views.tag_view, name="tag"),
-    path("<str:subject_url>/<str:course_url>/", views.course_view),
+    path("course/<str:subject_url>/<str:course_url>/", views.course_view),
 ]
diff --git a/studyguides/apps/courses/views.py b/studyguides/apps/courses/views.py
index dea3d06..812cddb 100644
--- a/studyguides/apps/courses/views.py
+++ b/studyguides/apps/courses/views.py
@@ -2,16 +2,17 @@ import random
 
 from django import http
 from django.shortcuts import render, redirect, reverse, get_object_or_404
+from django.contrib.auth.decorators import login_required
 
 from .models import Subject, Course, Guide, Tag
 
-
+@login_required
 def subject_view(request, subject_url):
     subject = get_object_or_404(Subject, url=subject_url)
     return render(request, "subject.html", {"subject": subject,
                                             "courses": subject.courses.all()})
 
-
+@login_required
 def course_view(request, subject_url, course_url):
     subject = get_object_or_404(Subject, url=subject_url)
     course = get_object_or_404(Course, url=course_url)
@@ -19,6 +20,7 @@ def course_view(request, subject_url, course_url):
                                            "course": course,
                                            "guides": [[g, g.tags.all()] for g in Guide.objects.filter(course=course)]})
 
+@login_required
 def tag_view(request, tag):
     tag = get_object_or_404(Tag, name=tag)
     return render(request, "tag.html", {"tag": tag, "guides": [[g, g.tags.all()] for g in tag.guide.all()]})
\ No newline at end of file
diff --git a/studyguides/apps/home/urls.py b/studyguides/apps/home/urls.py
index 1aaab90..35cad81 100644
--- a/studyguides/apps/home/urls.py
+++ b/studyguides/apps/home/urls.py
@@ -4,6 +4,6 @@ from . import views
 app_name = "home"
 
 urlpatterns = [
-    path("", views.index_view, name = "index"), 
+    path("all/", views.index_view, name="index"), 
 ]
 
diff --git a/studyguides/apps/home/views.py b/studyguides/apps/home/views.py
index facda87..9c0b8c6 100644
--- a/studyguides/apps/home/views.py
+++ b/studyguides/apps/home/views.py
@@ -1,10 +1,11 @@
 from django.shortcuts import render, redirect
 from django.http import HttpResponse
 from django.apps import apps
+from django.contrib.auth.decorators import login_required
 
 Subject = apps.get_model("courses", "Subject")
 Course = apps.get_model("courses", "Course")
 
-
+@login_required
 def index_view(request):
     return render(request, "home.html", {"subjects": [(subject, Course.objects.filter(subject=subject)) for subject in Subject.objects.all()]})
diff --git a/studyguides/apps/users/admin.py b/studyguides/apps/users/admin.py
index f9c7057..5c8f67d 100644
--- a/studyguides/apps/users/admin.py
+++ b/studyguides/apps/users/admin.py
@@ -1,7 +1,8 @@
 from django.contrib import admin
-from django.contrib.auth.admin import UserAdmin
-from .models import User
+
+from .models import Group, User
 
 # Register your models here.
 
-admin.site.register(User, UserAdmin)
+admin.site.register(User)
+admin.site.register(Group)
diff --git a/studyguides/apps/users/migrations/0001_initial.py b/studyguides/apps/users/migrations/0001_initial.py
new file mode 100644
index 0000000..ee7b1ee
--- /dev/null
+++ b/studyguides/apps/users/migrations/0001_initial.py
@@ -0,0 +1,50 @@
+# Generated by Django 3.0.6 on 2020-10-27 14:01
+
+from django.conf import settings
+from django.db import migrations, models
+import studyguides.apps.users.models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='User',
+            fields=[
+                ('password', models.CharField(max_length=128, verbose_name='password')),
+                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+                ('id', models.AutoField(primary_key=True, serialize=False)),
+                ('username', models.CharField(max_length=32, unique=True)),
+                ('first_name', models.CharField(max_length=35)),
+                ('last_name', models.CharField(max_length=70)),
+                ('email', models.EmailField(max_length=50)),
+                ('is_active', models.BooleanField(default=True)),
+                ('is_service', models.BooleanField(default=False)),
+                ('is_student', models.BooleanField(default=False)),
+                ('is_teacher', models.BooleanField(default=False)),
+                ('is_superuser', models.BooleanField(default=False)),
+                ('_is_staff', models.BooleanField(default=False)),
+                ('date_joined', models.DateTimeField(auto_now_add=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+            managers=[
+                ('objects', studyguides.apps.users.models.UserManager()),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Group',
+            fields=[
+                ('id', models.AutoField(primary_key=True, serialize=False)),
+                ('is_service', models.BooleanField(default=False)),
+                ('name', models.CharField(max_length=32)),
+                ('users', models.ManyToManyField(related_name='unix_groups', to=settings.AUTH_USER_MODEL)),
+            ],
+        ),
+    ]
diff --git a/studyguides/apps/context_processors.py b/studyguides/apps/users/migrations/__init__.py
similarity index 100%
rename from studyguides/apps/context_processors.py
rename to studyguides/apps/users/migrations/__init__.py
diff --git a/studyguides/apps/users/models.py b/studyguides/apps/users/models.py
index f3fc791..737fa0b 100644
--- a/studyguides/apps/users/models.py
+++ b/studyguides/apps/users/models.py
@@ -1,48 +1,82 @@
-from django.contrib.auth.models import AbstractUser
-from django.db import models
-
-from social_django.utils import load_strategy
-
-import requests
 import logging
 
+from django.contrib.auth.models import AbstractBaseUser
+from django.contrib.auth.models import UserManager as DjangoUserManager
+from django.db import models
+
 logger = logging.getLogger(__name__)
 
-# Create your models here.
-class User(AbstractUser):
-    id = models.AutoField(primary_key = True)
-    full_name = models.CharField(max_length = 105)
+
+class UserManager(DjangoUserManager):
+    pass
+
+
+class User(AbstractBaseUser):
+    objects = UserManager()
+
+    USERNAME_FIELD = "username"
+    EMAIL_FIELD = "email"
+    REQUIRED_FIELDS = ["first_name", "last_name", "email", "is_teacher"]
+
+    id = models.AutoField(primary_key=True)
+
+    username = models.CharField(unique=True, max_length=32, null=False, blank=False)
+    first_name = models.CharField(max_length=35, null=False, blank=False)
+    last_name = models.CharField(max_length=70, null=False, blank=False)
+    email = models.EmailField(max_length=50, null=False, blank=False)
+
+    is_active = models.BooleanField(default=True, null=False)
+    is_service = models.BooleanField(default=False, null=False)
+    is_student = models.BooleanField(default=False, null=False)
+    is_teacher = models.BooleanField(default=False, null=False)
+    is_superuser = models.BooleanField(default=False, null=False)
+    _is_staff = models.BooleanField(default=False, null=False)
+
+    date_joined = models.DateTimeField(auto_now_add=True)
+
+    def has_perm(self, perm, obj=None) -> bool:  # pylint: disable=unused-argument
+        return self.is_superuser
+
+    def has_module_perms(self, app_label) -> bool:  # pylint: disable=unused-argument
+        return self.is_superuser
 
     @property
-    def short_name(self):
-        return self.username
-    def __str__(self):
+    def is_staff(self) -> bool:
+        return self._is_staff or self.is_superuser
+
+    @is_staff.setter
+    def is_staff(self, staff: bool) -> None:
+        self._is_staff = staff
+
+    @property
+    def full_name(self) -> str:
+        return self.first_name + " " + self.last_name
+
+    @property
+    def short_name(self) -> str:
+        return self.first_name
+
+    def get_full_name(self) -> str:
         return self.full_name
-    def empty_fields(self):
-        list = []
-        for field in User._meta.fields:
-            list.append((field.value_from_object(self),field))
-        return list
-    def api_request(self, url, params={}, refresh=True):
-        s = self.get_social_auth()
-        params.update({"format": "json"})
-        params.update({"access_token": s.access_token})
-        r = requests.get(
-            "https://ion.tjhsst.edu/api/{}".format(url),
-            params = params,
-        )
-        if r.status_code == 401:
-            if refresh:
-                try:
-                    self.get_social_auth().refresh_token(load_strategy())
-                except BaseException as e:
-                    logger.exception(str(e))
-                return self.api_request(url, params, False)
-            else:
-                logger.error(
-                    "Ion API Request Failure: {} {}".format(r.status_code,
-                                                            r.json()))
-        return r.json()
+
+    def get_short_name(self) -> str:
+        return self.short_name
 
     def get_social_auth(self):
-        return self.social_auth.get(provider = "ion")
+        return self.social_auth.get(provider="ion")
+
+    def __str__(self):
+        return self.username
+
+    def __repr__(self):
+        return "<User: {} ({})>".format(self.username, self.id)
+
+
+class Group(models.Model):
+    id = models.AutoField(primary_key=True)
+    is_service = models.BooleanField(default=False)
+    name = models.CharField(max_length=32)
+    users = models.ManyToManyField(User, related_name="unix_groups")
+
+    def __str__(self):
+        return self.name
diff --git a/studyguides/apps/users/tests.py b/studyguides/apps/users/tests.py
deleted file mode 100644
index 7ce503c..0000000
--- a/studyguides/apps/users/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/studyguides/apps/users/urls.py b/studyguides/apps/users/urls.py
deleted file mode 100644
index f62712b..0000000
--- a/studyguides/apps/users/urls.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django.urls import path
-
-from . import views
-
-app_name = "users"
-
-urlpatterns = [
-
-]
-
diff --git a/studyguides/apps/users/views.py b/studyguides/apps/users/views.py
deleted file mode 100644
index 494a254..0000000
--- a/studyguides/apps/users/views.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from django.shortcuts import render, redirect
-from django import http
-from .models import User
-from django.forms import formset_factory
-# Create your views here.
-
diff --git a/studyguides/settings/__init__.py b/studyguides/settings/__init__.py
index 67c5255..166e262 100644
--- a/studyguides/settings/__init__.py
+++ b/studyguides/settings/__init__.py
@@ -42,9 +42,9 @@ INSTALLED_APPS = [
     'django.contrib.staticfiles',
     'social_django',
     'studyguides.apps.courses',
-    'studyguides.apps.home',
+    'studyguides.apps.auth',
     'studyguides.apps.users',
-    'studyguides.apps.auth.apps.AuthConfig',
+    'studyguides.apps.home',
 ]
 
 MIDDLEWARE = [
@@ -72,8 +72,6 @@ TEMPLATES = [
                 'django.template.context_processors.request',
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
-                'social_django.context_processors.backends',
-                'social_django.context_processors.login_redirect',
             ],
         },
     },
@@ -111,12 +109,9 @@ AUTH_PASSWORD_VALIDATORS = [
     },
 ]
 
-AUTHENTICATION_BACKENDS = (
-    'studyguides.apps.auth.oauth.IonOauth2',
-    'django.contrib.auth.backends.ModelBackend',
-)
+AUTHENTICATION_BACKENDS = ('studyguides.apps.auth.oauth.IonOauth2',)
 
-SOCIAL_AUTH_USER_FIELDS = ['username', 'full_name', 'first_name', 'last_name', 'email', 'id']
+SOCIAL_AUTH_USER_FIELDS = ['username', 'first_name', 'last_name', 'email', 'id', "is_teacher", "is_student",]
 
 SOCIAL_AUTH_URL_NAMESPACE = 'social'
 
@@ -134,8 +129,6 @@ SOCIAL_AUTH_PIPELINE = (
 
 AUTH_USER_MODEL = "users.User"
 
-SOCIAL_AUTH_ALWAYS_ASSOCIATE = True
-
 # Internationalization
 # https://docs.djangoproject.com/en/2.2/topics/i18n/
 
@@ -150,10 +143,12 @@ USE_L10N = True
 USE_TZ = True
 
 LOGIN_URL = "auth:login"
-LOGIN_REDIRECT_URL = "users:index"
-LOGOUT_REDIRECT_URL = "home:index"
+LOGIN_REDIRECT_URL = "auth:index"
 
-SOCIAL_AUTH_LOGIN_ERROR_URL = '/'
+SESSION_SAVE_EVERY_REQUEST = True
+
+SOCIAL_AUTH_ALWAYS_ASSOCIATE = True
+SOCIAL_AUTH_LOGIN_ERROR_URL = "/"
 SOCIAL_AUTH_RAISE_EXCEPTIONS = False
 
 # Static files (CSS, JavaScript, Images)
diff --git a/studyguides/static/login.css b/studyguides/static/login.css
new file mode 100644
index 0000000..9e0c8ee
--- /dev/null
+++ b/studyguides/static/login.css
@@ -0,0 +1,43 @@
+.btn.btn-ion {
+    text-decoration: none;
+    color: #484848;
+    display: inline-block;
+    line-height: 18px;
+    padding: 7px 10px;
+    margin: 2px 0;
+    font-size: 13px;
+    font-weight: bold;
+    text-shadow: 0 1px 0 rgba(255,255,255,.9);
+    white-space: nowrap;
+    -webkit-border-radius: 3px;
+    -moz-border-radius: 3px;
+    border-radius: 3px;
+    background: #f7f7f4;
+    background: -moz-linear-gradient(top,#f7f7f4 0%,#eaeaea 100%);
+    background: -webkit-linear-gradient(top,#f7f7f4 0%,#eaeaea 100%);
+    background: linear-gradient(to bottom,#f7f7f4 0%,#eaeaea 100%);
+    border: 1px solid #ddd;
+    border-bottom-color: #c5c5c5;
+    -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.05);
+    -moz-box-shadow: 0 1px 3px rgba(0,0,0,.05);
+    -pie-box-shadow: none;
+    box-shadow: 0 1px 3px rgba(0,0,0,.05);
+    vertical-align: middle;
+    -webkit-user-select: none;
+    -khtml-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    -o-appearance: none;
+    appearance: none;
+}
+
+.login-box {
+    text-align: center;
+    padding: 15px;
+    border: 1px solid rgb(24, 82, 103);
+    margin: 15px auto;
+    max-width: 438px;
+}
\ No newline at end of file
diff --git a/studyguides/templates/login.html b/studyguides/templates/login.html
new file mode 100644
index 0000000..fb2e1b5
--- /dev/null
+++ b/studyguides/templates/login.html
@@ -0,0 +1,17 @@
+{% extends 'base.html' %}
+
+{% load static %}
+
+{% block head %}
+    <link rel='stylesheet' href="{% static 'login.css' %}">
+{% endblock %}
+
+{% block main %}
+    <main>
+        <h1 class='header_title'>Study Guides</h1>
+        <div class='login-box'>
+            <p><b>Login in with your Intranet account</b> to access the Study Guide website.</p>
+            <a href="{% url 'social:begin' 'ion' %}{% if request.GET.next %}?next={{ request.GET.next|urlencode }}{% endif %}" class='btn btn-ion'>Log in with Ion</a>
+        </div>
+    </main>
+{% endblock %}
\ No newline at end of file
diff --git a/studyguides/urls.py b/studyguides/urls.py
index f70d8f6..f31774d 100644
--- a/studyguides/urls.py
+++ b/studyguides/urls.py
@@ -20,11 +20,10 @@ from django.conf.urls.static import static
 
 urlpatterns = [
     path('admin/', admin.site.urls),
-
-    path('auth/', include('studyguides.apps.auth.urls', namespace='auth')),
+    path('', include('social_django.urls', namespace='social')),
+    path('', include('studyguides.apps.auth.urls', namespace='auth')),
     path('', include('studyguides.apps.courses.urls', namespace='courses')),
     path('', include('studyguides.apps.home.urls', namespace='home')),
-    path('', include('social_django.urls', namespace='social')),
 
 ]
 if settings.DEBUG: