diff --git a/eos/nsauth/election.py b/eos/nsauth/election.py
new file mode 100644
index 0000000..c3c4240
--- /dev/null
+++ b/eos/nsauth/election.py
@@ -0,0 +1,30 @@
+# Eos - Verifiable elections
+# Copyright © 2017-2019 RunasSudo (Yingtong Li)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from eos.base.election import *
+from eos.core.objects import *
+
+class NationStatesUser(User):
+ username = StringField()
+
+ @property
+ def name(self):
+ return self.username
+
+ def matched_by(self, other):
+ if not isinstance(other, NationStatesUser):
+ return False
+ return other.username.lower().strip().replace(' ', '_') == self.username.lower().strip().replace(' ', '_')
diff --git a/eosweb/nsauth/main.py b/eosweb/nsauth/main.py
new file mode 100644
index 0000000..ff83f46
--- /dev/null
+++ b/eosweb/nsauth/main.py
@@ -0,0 +1,46 @@
+# Eos - Verifiable elections
+# Copyright © 2017-2019 RunasSudo (Yingtong Li)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import flask
+
+from eos.nsauth.election import *
+
+import urllib.request, urllib.parse
+
+blueprint = flask.Blueprint('eosweb.nsauth', __name__, template_folder='templates')
+
+app = None
+
+@blueprint.record
+def reddit_register(setup_state):
+ global app
+ app = setup_state.app
+
+@blueprint.route('/auth/nationstates/login')
+def nationstates_login():
+ return flask.render_template('auth/nationstates/login.html')
+
+@blueprint.route('/auth/nationstates/authenticate', methods=['POST'])
+def nationstates_authenticate():
+ username = flask.request.form['username'].lower().strip().replace(' ', '_')
+
+ with urllib.request.urlopen(urllib.request.Request('https://www.nationstates.net/cgi-bin/api.cgi?a=verify&' + urllib.parse.urlencode({'nation': username, 'checksum': flask.request.form['checksum']}), headers={'User-Agent': app.config['NATIONSTATES_USER_AGENT']})) as resp:
+ if resp.read().decode('utf-8').strip() != '1':
+ return flask.render_template('auth/nationstates/login.html', error='The nation name or verification code you entered was invalid. Please check your details and try again. If the issue persists, contact the election administrator.')
+
+ flask.session['user'] = NationStatesUser(username=username)
+
+ return flask.redirect(flask.url_for('login_complete'))
diff --git a/eosweb/nsauth/settings.py b/eosweb/nsauth/settings.py
new file mode 100644
index 0000000..93ac9c2
--- /dev/null
+++ b/eosweb/nsauth/settings.py
@@ -0,0 +1,17 @@
+# Eos - Verifiable elections
+# Copyright © 2017-2019 RunasSudo (Yingtong Li)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+NATIONSTATES_USER_AGENT = 'FIXME'
diff --git a/eosweb/nsauth/templates/auth/nationstates/login.html b/eosweb/nsauth/templates/auth/nationstates/login.html
new file mode 100644
index 0000000..f8c78b5
--- /dev/null
+++ b/eosweb/nsauth/templates/auth/nationstates/login.html
@@ -0,0 +1,51 @@
+{% extends 'semantic_base.html' %}
+
+{#
+ Eos - Verifiable elections
+ Copyright © 2017-2019 RunasSudo (Yingtong Li)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+#}
+
+{% block title %}Log in{% endblock %}
+
+{% block basecontent %}
+
+
+
1. Log in to NationStates below if necessary, and copy your Login Verification Code.
+
+
2. Type your nation name and paste your Login Verification Code into the form below.
+
+
+
+{% endblock %}