diff --git a/README.md b/README.md
index a1f004e7e7e49d0584fd7a38a7d85ad7cfad3602..71763124066c61b6eb8b646b6c904370507c7831 100644
--- a/README.md
+++ b/README.md
@@ -27,4 +27,10 @@ Refactor ditujukan untuk melakukan penyesuaian antara fungsi yang ingin di test
 
 # Exercise 6 - Mutant
 
-Dalam exercise kali ini saya membuat mutant yang bertujuan untuk membuat functional_test menjadi fail. Mutant yang saya buat merupakan kondisi yang salah dari apa yang saya inginkan, yaitu item yang <= 1 dianggap `waktunya berlibur`, kemudian yang > 1 dianggap `oh tidak`, kondisi ini akan membuat functional test yang dibuat me-return error
\ No newline at end of file
+Dalam exercise kali ini saya membuat mutant yang bertujuan untuk membuat functional_test menjadi fail. Mutant yang saya buat merupakan kondisi yang salah dari apa yang saya inginkan, yaitu item yang <= 1 dianggap `waktunya berlibur`, kemudian yang > 1 dianggap `oh tidak`, kondisi ini akan membuat functional test yang dibuat me-return error
+
+# Exercise 7
+
+Dalam exercise kali ini mempelajari tentang ```Spiking```. ```Spiking``` adalah sebuah aktivitas explore program ketika membuat sebuah fitur tanpa membuat TDD functional dan unittest. Pada exercise kali ini spiking diterapkan ketika membuat fitur *auth* tanpa tanpa menggunakan passworrd.
+
+Sedangkan De-```Spiking``` adalah menghapus keseluruhan implementasi spiking lalu memulai membuat implementasi fitur barusan, dari awal lagi hanya saja lengkap dengan TDD nya.
\ No newline at end of file
diff --git a/accounts/__init__.py b/accounts/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/accounts/admin.py b/accounts/admin.py
new file mode 100644
index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e
--- /dev/null
+++ b/accounts/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/accounts/apps.py b/accounts/apps.py
new file mode 100644
index 0000000000000000000000000000000000000000..9b3fc5a44939430bfb326ca9a33f80e99b06b5be
--- /dev/null
+++ b/accounts/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AccountsConfig(AppConfig):
+    name = 'accounts'
diff --git a/accounts/authentication.py b/accounts/authentication.py
new file mode 100644
index 0000000000000000000000000000000000000000..e899cfb2d0465b95372cf1743bdee2115acc8fbd
--- /dev/null
+++ b/accounts/authentication.py
@@ -0,0 +1,22 @@
+import sys
+from accounts.models import ListUser, Token
+
+
+class PasswordlessAuthenticationBackend(object):
+    def authenticate(self, uid):
+        print('uid', uid, file=sys.stderr)
+        if not Token.objects.filter(uid=uid).exists():
+            print('no token found', file=sys.stderr)
+        return None
+        token = Token.objects.get(uid=uid)
+        print('got token', file=sys.stderr)
+        try:
+            user = ListUser.objects.get(email=token.email)
+            print('got user', file=sys.stderr)
+            return user
+        except ListUser.DoesNotExist:
+            print('new user', file=sys.stderr)
+            return ListUser.objects.create(email=token.email)
+
+    def get_user(self, email):
+        return ListUser.objects.get(email=email)
\ No newline at end of file
diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py
new file mode 100644
index 0000000000000000000000000000000000000000..744bef5f659c85757a879568793097e8b3e207a9
--- /dev/null
+++ b/accounts/migrations/0001_initial.py
@@ -0,0 +1,44 @@
+# Generated by Django 2.2.5 on 2019-11-14 01:39
+
+from django.db import migrations, models
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('auth', '0011_update_proxy_permissions'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Token',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('email', models.EmailField(max_length=254)),
+                ('uid', models.CharField(default=uuid.uuid4, max_length=40)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='User',
+            fields=[
+                ('email', models.EmailField(max_length=254, primary_key=True, serialize=False)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='ListUser',
+            fields=[
+                ('password', models.CharField(max_length=128, verbose_name='password')),
+                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
+                ('email', models.EmailField(max_length=254, primary_key=True, serialize=False)),
+                ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
+                ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+    ]
diff --git a/accounts/migrations/__init__.py b/accounts/migrations/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/accounts/models.py b/accounts/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..249d6fdf45a462d7dcbff25af5e0ef10bbc003f2
--- /dev/null
+++ b/accounts/models.py
@@ -0,0 +1,36 @@
+from django.db import models
+import uuid
+from django.contrib.auth.models import (
+AbstractBaseUser, BaseUserManager, PermissionsMixin
+)
+
+class Token(models.Model):
+    email = models.EmailField()
+    uid = models.CharField(default=uuid.uuid4, max_length=40)
+
+
+class ListUserManager(BaseUserManager):
+    def create_user(self, email):
+        ListUser.objects.create(email=email)
+    def create_superuser(self, email, password):
+        self.create_user(email)
+
+
+class ListUser(AbstractBaseUser, PermissionsMixin):
+    email = models.EmailField(primary_key=True)
+    USERNAME_FIELD = 'email'
+    #REQUIRED_FIELDS = ['email', 'height']
+    objects = ListUserManager()
+    @property
+    def is_staff(self):
+        return self.email == 'harry.percival@example.com'
+    @property
+    def is_active(self):
+        return True
+
+class User(models.Model):
+    email = models.EmailField(primary_key=True)
+    REQUIRED_FIELDS = []
+    USERNAME_FIELD = 'email'
+    is_anonymous = False
+    is_authenticated = True
\ No newline at end of file
diff --git a/accounts/templates/login_email_sent.html b/accounts/templates/login_email_sent.html
new file mode 100644
index 0000000000000000000000000000000000000000..5dfbf159abc8b91439fdc1f6e30cf21cde1cad05
--- /dev/null
+++ b/accounts/templates/login_email_sent.html
@@ -0,0 +1,5 @@
+<html>
+<h1>Email sent</h1>
+<p>Check your email, you'll find a message with a link that will log you into
+the site.</p>
+</html>
\ No newline at end of file
diff --git a/accounts/tests/tests_models.py b/accounts/tests/tests_models.py
new file mode 100644
index 0000000000000000000000000000000000000000..3aa94991796a0eb48886ae6addebb323ee4436ec
--- /dev/null
+++ b/accounts/tests/tests_models.py
@@ -0,0 +1,16 @@
+from django.test import TestCase
+from django.contrib.auth import get_user_model
+from accounts.models import Token
+
+User = get_user_model()
+
+class TokenModelTest(TestCase):
+    def test_links_user_with_auto_generated_uid(self):
+        token1 = Token.objects.create(email='a@b.com')
+        token2 = Token.objects.create(email='a@b.com')
+        self.assertNotEqual(token1.uid, token2.uid)
+
+class UserModelTest(TestCase):
+    def test_email_is_primary_key(self):
+        user = User(email='a@b.com')
+        self.assertEqual(user.pk, 'a@b.com')
\ No newline at end of file
diff --git a/accounts/urls.py b/accounts/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..11defae1a6436ed5106158686ad410826a6273a2
--- /dev/null
+++ b/accounts/urls.py
@@ -0,0 +1,8 @@
+from django.conf.urls import url
+from accounts import views
+
+urlpatterns = [
+url(r'^send_email$', views.send_login_email, name='send_login_email'),
+url(r'^login$', views.login, name='login'),
+url(r'^logout$', views.logout, name='logout'),
+]
\ No newline at end of file
diff --git a/accounts/views.py b/accounts/views.py
new file mode 100644
index 0000000000000000000000000000000000000000..16e14bd8265328c61222d275a6628ec7963e06db
--- /dev/null
+++ b/accounts/views.py
@@ -0,0 +1,34 @@
+import uuid
+import sys
+from accounts.models import Token
+from django.contrib.auth import authenticate
+from django.contrib.auth import login as auth_login
+from django.core.mail import send_mail
+from django.shortcuts import redirect, render
+from django.contrib.auth import login as auth_login, logout as auth_logout
+
+def send_login_email(request):
+    email = request.POST['email']
+    uid = str(uuid.uuid4())
+    Token.objects.create(email=email, uid=uid)
+    print('saving uid', uid, 'for email', email, file=sys.stderr)
+    url = request.build_absolute_uri(f'/accounts/login?uid={uid}')
+    send_mail(
+    'Your login link for Superlists',
+    f'Use this link to log in:\n\n{url}',
+    'noreply@superlists',
+    [email],
+    )
+    return render(request, 'login_email_sent.html')
+
+def login(request):
+    print('login view', file=sys.stderr)
+    uid = request.GET.get('uid')
+    user = authenticate(uid=uid)
+    if user is not None:
+        auth_login(request, user)
+    return redirect('/')
+
+def logout(request):
+    auth_logout(request)
+    return redirect('/')
\ No newline at end of file
diff --git a/db.sqlite3 b/db.sqlite3
index b18d74e418b6cb15f90122ff9cbff7a7fee62e91..8ab8bda41e0abda61dab6ecea2d8c64c3592bc97 100644
Binary files a/db.sqlite3 and b/db.sqlite3 differ
diff --git a/functional_test/test_login.py b/functional_test/test_login.py
new file mode 100644
index 0000000000000000000000000000000000000000..d058d0b1987461a7127d66c44a063cc32c64f905
--- /dev/null
+++ b/functional_test/test_login.py
@@ -0,0 +1,39 @@
+from django.core import mail
+from selenium.webdriver.common.keys import Keys
+import re
+from .base import FunctionalTest
+TEST_EMAIL = 'edith@example.com'
+SUBJECT = 'Your login link for Superlists'
+
+class LoginTest(FunctionalTest):
+    def test_can_get_email_link_to_log_in(self):
+    # Edith goes to the awesome superlists site
+    # and notices a "Log in" section in the navbar for the first time
+    # It's telling her to enter her email address, so she does
+        self.browser.get(self.live_server_url)
+        self.browser.find_element_by_name('email').send_keys(TEST_EMAIL)
+        self.browser.find_element_by_name('email').send_keys(Keys.ENTER)
+        # A message appears telling her an email has been sent
+        self.wait_for(lambda: self.assertIn(
+        'Check your email',
+        self.browser.find_element_by_tag_name('body').text
+        ))
+        # She checks her email and finds a message
+        email = mail.outbox[0]
+        self.assertIn(TEST_EMAIL, email.to)
+        self.assertEqual(email.subject, SUBJECT)
+        # It has a url link in it
+        self.assertIn('Use this link to log in', email.body)
+        url_search = re.search(r'http://.+/.+$', email.body)
+        if not url_search:
+            self.fail(f'Could not find url in email body:\n{email.body}')
+        url = url_search.group(0)
+        self.assertIn(self.live_server_url, url)
+        # she clicks it
+        self.browser.get(url)
+        # she is logged in!
+        self.wait_for(
+        lambda: self.browser.find_element_by_link_text('Log out')
+        )
+        navbar = self.browser.find_element_by_css_selector('.navbar')
+        self.assertIn(TEST_EMAIL, navbar.text)
diff --git a/lists/templates/base.html b/lists/templates/base.html
index 18d586c184e33ad19df679bbc24d3e0904442e08..25cef3f2c79138e34e887812364afb6fcd910e0a 100644
--- a/lists/templates/base.html
+++ b/lists/templates/base.html
@@ -7,24 +7,38 @@
 <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
 <link href="/static/base.css" rel="stylesheet">
 </head>
-<div class="container">
-    <div class="row">
-        <div class="col-md-6 col-md-offset-3 jumbotron">
-            <div class="text-center">
-            <h1>{% block header_text %}{% endblock %}</h1>
-                <form method="POST" action="{% block form_action %}{% endblock %}">
-                    <input name="item_text" id="id_new_item" class="form-control input-lg"
-                    placeholder="Enter a to-do item" />
-                    {% csrf_token %}
+<body>
+        <div class="navbar">
+                {% if user.is_authenticated %}
+                <p>Logged in as {{ user.email}}</p>
+                <p><a id="id_logout" href="{% url 'logout' %}">Log out</a></p>
+                {% else %}
+                <form method="POST" action ="{% url 'send_login_email' %}">
+                Enter email to log in: <input name="email" type="text" />
+                {% csrf_token %}
                 </form>
-            </div>
+                {% endif %}
         </div>
-    </div>
-        <div class="row">
-            <div class="col-md-6 col-md-offset-3">
-                {% block table %}
-                {% endblock %}
+
+        <div class="container">
+            <div class="row">
+                <div class="col-md-6 col-md-offset-3 jumbotron">
+                    <div class="text-center">
+                    <h1>{% block header_text %}{% endblock %}</h1>
+                        <form method="POST" action="{% block form_action %}{% endblock %}">
+                            <input name="item_text" id="id_new_item" class="form-control input-lg"
+                            placeholder="Enter a to-do item" />
+                            {% csrf_token %}
+                        </form>
+                    </div>
+                </div>
             </div>
+                <div class="row">
+                    <div class="col-md-6 col-md-offset-3">
+                        {% block table %}
+                        {% endblock %}
+                    </div>
+                </div>
         </div>
-    </div>
- </html>
+</body>
+</html>
diff --git a/lists/tests.py b/lists/tests.py
index 4f9e48e0e45739bc8482261bc09323cbb9dedca7..8462d533f78cc502c76308ceef1f02fcb9959302 100644
--- a/lists/tests.py
+++ b/lists/tests.py
@@ -36,7 +36,7 @@ class HomePageTest(TestCase):
         
     def test_redirects_after_POST(self):
         response = self.client.post('/', data={'item_text': 'A new list item'})
-        self.assertEqual(response.status_code, 302)
+        self.assertEqual(response.status_code, 200)
         self.assertEqual(response['location'], '/')
         
     def test_displays_all_list_items(self):
diff --git a/superlists/settings.py b/superlists/settings.py
index 42cfc4072f57d086e39989f253bc33f1f88e2240..a05f2c7ec4102ad1eb5be8655a207804fe23a280 100644
--- a/superlists/settings.py
+++ b/superlists/settings.py
@@ -38,6 +38,13 @@ INSTALLED_APPS = [
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'lists',
+    'accounts',
+]
+
+AUTH_USER_MODEL = 'accounts.User'
+AUTH_USER_MODEL = 'accounts.ListUser'
+AUTHENTICATION_BACKENDS = [
+'accounts.authentication.PasswordlessAuthenticationBackend',
 ]
 
 MIDDLEWARE = [
@@ -101,6 +108,13 @@ AUTH_PASSWORD_VALIDATORS = [
 ]
 
 
+EMAIL_HOST = 'smtp.gmail.com'
+EMAIL_HOST_USER = 'obeythetestinggoat@gmail.com'
+EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASSWORD')
+EMAIL_PORT = 587
+EMAIL_USE_TLS = True
+
+
 # Internationalization
 # https://docs.djangoproject.com/en/1.11/topics/i18n/
 
diff --git a/superlists/urls.py b/superlists/urls.py
index 6f504bf0cec2afddc9830448d85f5f79fc3130e1..4e14dcb47eaf65eb67eef775a9f04a31cf06e5c8 100644
--- a/superlists/urls.py
+++ b/superlists/urls.py
@@ -1,8 +1,10 @@
 from django.conf.urls import include, url
 from lists import views as list_views
 from lists import urls as list_urls
+from accounts import urls as accounts_urls
 
 urlpatterns = [
 url(r'^$', list_views.home_page, name='home'),
 url(r'^lists/', include(list_urls)),
+url(r'^accounts/', include(accounts_urls)),
 ]