diff --git a/common/djangoapps/student/migrations/0032_add_field_UserProfile_country_add_field_UserProfile_city.py b/common/djangoapps/student/migrations/0032_add_field_UserProfile_country_add_field_UserProfile_city.py
new file mode 100644
index 0000000000000000000000000000000000000000..bf35f208ed485bc08a31d0db1d07493f722273b4
--- /dev/null
+++ b/common/djangoapps/student/migrations/0032_add_field_UserProfile_country_add_field_UserProfile_city.py
@@ -0,0 +1,146 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding field 'UserProfile.country'
+        db.add_column('auth_userprofile', 'country',
+                      self.gf('django_countries.fields.CountryField')(max_length=2, null=True, blank=True),
+                      keep_default=False)
+
+        # Adding field 'UserProfile.city'
+        db.add_column('auth_userprofile', 'city',
+                      self.gf('django.db.models.fields.TextField')(null=True, blank=True),
+                      keep_default=False)
+
+
+    def backwards(self, orm):
+        # Deleting field 'UserProfile.country'
+        db.delete_column('auth_userprofile', 'country')
+
+        # Deleting field 'UserProfile.city'
+        db.delete_column('auth_userprofile', 'city')
+
+
+    models = {
+        'auth.group': {
+            'Meta': {'object_name': 'Group'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+            'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+        },
+        'auth.permission': {
+            'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+            'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+        },
+        'auth.user': {
+            'Meta': {'object_name': 'User'},
+            'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+            'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+            'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+            'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+            'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+            'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+        },
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        'student.anonymoususerid': {
+            'Meta': {'object_name': 'AnonymousUserId'},
+            'anonymous_user_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'}),
+            'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+        },
+        'student.courseenrollment': {
+            'Meta': {'ordering': "('user', 'course_id')", 'unique_together': "(('user', 'course_id'),)", 'object_name': 'CourseEnrollment'},
+            'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '100'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
+        },
+        'student.courseenrollmentallowed': {
+            'Meta': {'unique_together': "(('email', 'course_id'),)", 'object_name': 'CourseEnrollmentAllowed'},
+            'auto_enroll': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
+        },
+        'student.pendingemailchange': {
+            'Meta': {'object_name': 'PendingEmailChange'},
+            'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'new_email': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
+        },
+        'student.pendingnamechange': {
+            'Meta': {'object_name': 'PendingNameChange'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'new_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
+            'rationale': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'})
+        },
+        'student.registration': {
+            'Meta': {'object_name': 'Registration', 'db_table': "'auth_registration'"},
+            'activation_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32', 'db_index': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
+        },
+        'student.userprofile': {
+            'Meta': {'object_name': 'UserProfile', 'db_table': "'auth_userprofile'"},
+            'allow_certificate': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
+            'city': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'country': ('django_countries.fields.CountryField', [], {'max_length': '2', 'null': 'True', 'blank': 'True'}),
+            'courseware': ('django.db.models.fields.CharField', [], {'default': "'course.xml'", 'max_length': '255', 'blank': 'True'}),
+            'gender': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}),
+            'goals': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'language': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
+            'level_of_education': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '6', 'null': 'True', 'blank': 'True'}),
+            'location': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
+            'mailing_address': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+            'meta': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}),
+            'year_of_birth': ('django.db.models.fields.IntegerField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'})
+        },
+        'student.userstanding': {
+            'Meta': {'object_name': 'UserStanding'},
+            'account_status': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
+            'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'standing_last_changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'standing'", 'unique': 'True', 'to': "orm['auth.User']"})
+        },
+        'student.usertestgroup': {
+            'Meta': {'object_name': 'UserTestGroup'},
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
+            'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.User']", 'db_index': 'True', 'symmetrical': 'False'})
+        }
+    }
+
+    complete_apps = ['student']
\ No newline at end of file
diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py
index a074d61cb9f630dfaf3202ffd0ac0001aaf0e237..619931f279bd73a8b6b4d236be863f0ba10038f2 100644
--- a/common/djangoapps/student/models.py
+++ b/common/djangoapps/student/models.py
@@ -29,6 +29,7 @@ from django.dispatch import receiver, Signal
 import django.dispatch
 from django.forms import ModelForm, forms
 from django.core.exceptions import ObjectDoesNotExist
+from django_countries import CountryField
 from track import contexts
 from track.views import server_track
 from eventtracking import tracker
@@ -213,6 +214,8 @@ class UserProfile(models.Model):
         choices=LEVEL_OF_EDUCATION_CHOICES
     )
     mailing_address = models.TextField(blank=True, null=True)
+    city = models.TextField(blank=True, null=True)
+    country = CountryField(blank=True, null=True)
     goals = models.TextField(blank=True, null=True)
     allow_certificate = models.BooleanField(default=1)
 
diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py
index 95ff269a3a22622cb8aaa9c78311c753d92a4ecb..8136e025406e2880eca7143282ea4725a300e6a5 100644
--- a/common/djangoapps/student/views.py
+++ b/common/djangoapps/student/views.py
@@ -825,6 +825,8 @@ def _do_create_account(post_vars):
     profile.level_of_education = post_vars.get('level_of_education')
     profile.gender = post_vars.get('gender')
     profile.mailing_address = post_vars.get('mailing_address')
+    profile.city = post_vars.get('city')
+    profile.country = post_vars.get('country')
     profile.goals = post_vars.get('goals')
 
     try:
@@ -849,6 +851,7 @@ def create_account(request, post_override=None):
     js = {'success': False}
 
     post_vars = post_override if post_override else request.POST
+    extra_fields = getattr(settings, 'REGISTRATION_EXTRA_FIELDS', {})
 
     # if doing signup for an external authorization, then get email, password, name from the eamap
     # don't use the ones from the form, since the user could have hacked those
@@ -877,18 +880,23 @@ def create_account(request, post_override=None):
             js['field'] = a
             return HttpResponse(json.dumps(js))
 
-    if post_vars.get('honor_code', 'false') != u'true':
+    if extra_fields.get('honor_code', 'required') == 'required' and \
+            post_vars.get('honor_code', 'false') != u'true':
         js['value'] = _("To enroll, you must follow the honor code.").format(field=a)
         js['field'] = 'honor_code'
         return HttpResponse(json.dumps(js))
 
     # Can't have terms of service for certain SHIB users, like at Stanford
-    tos_not_required = (settings.FEATURES.get("AUTH_USE_SHIB") and
-                        settings.FEATURES.get('SHIB_DISABLE_TOS') and
-                        DoExternalAuth and
-                        eamap.external_domain.startswith(external_auth.views.SHIBBOLETH_DOMAIN_PREFIX))
+    tos_required = (
+        not settings.FEATURES.get("AUTH_USE_SHIB") or
+        not settings.FEATURES.get("SHIB_DISABLE_TOS") or
+        not DoExternalAuth or
+        not eamap.external_domain.startswith(
+            external_auth.views.SHIBBOLETH_DOMAIN_PREFIX
+        )
+    )
 
-    if not tos_not_required:
+    if tos_required:
         if post_vars.get('terms_of_service', 'false') != u'true':
             js['value'] = _("You must accept the terms of service.").format(field=a)
             js['field'] = 'terms_of_service'
@@ -900,20 +908,36 @@ def create_account(request, post_override=None):
     # this is a good idea
     # TODO: Check password is sane
 
-    required_post_vars = ['username', 'email', 'name', 'password', 'terms_of_service', 'honor_code']
-    if tos_not_required:
-        required_post_vars = ['username', 'email', 'name', 'password', 'honor_code']
-
-    for a in required_post_vars:
-        if len(post_vars[a]) < 2:
-            error_str = {'username': 'Username must be minimum of two characters long.',
-                         'email': 'A properly formatted e-mail is required.',
-                         'name': 'Your legal name must be a minimum of two characters long.',
-                         'password': 'A valid password is required.',
-                         'terms_of_service': 'Accepting Terms of Service is required.',
-                         'honor_code': 'Agreeing to the Honor Code is required.'}
-            js['value'] = error_str[a]
-            js['field'] = a
+    required_post_vars = ['username', 'email', 'name', 'password']
+    required_post_vars += [fieldname for fieldname, val in extra_fields.items()
+                           if val == 'required']
+    if tos_required:
+        required_post_vars.append('terms_of_service')
+
+    for field_name in required_post_vars:
+        if field_name in ('gender', 'level_of_education'):
+            min_length = 1
+        else:
+            min_length = 2
+
+        if len(post_vars[field_name]) < min_length:
+            error_str = {
+                'username': _('Username must be minimum of two characters long.'),
+                'email': _('A properly formatted e-mail is required.'),
+                'name': _('Your legal name must be a minimum of two characters long.'),
+                'password': _('A valid password is required.'),
+                'terms_of_service': _('Accepting Terms of Service is required.'),
+                'honor_code': _('Agreeing to the Honor Code is required.'),
+                'level_of_education': _('A level of education is required.'),
+                'gender': _('Your gender is required'),
+                'year_of_birth': _('Your year of birth is required'),
+                'mailing_address': _('Your mailing address is required'),
+                'goals': _('A description of your goals is required'),
+                'city': _('A city is required'),
+                'country': _('A country is required')
+            }
+            js['value'] = error_str[field_name]
+            js['field'] = field_name
             return HttpResponse(json.dumps(js))
 
     try:
diff --git a/lms/djangoapps/courseware/tests/test_registration_extra_vars.py b/lms/djangoapps/courseware/tests/test_registration_extra_vars.py
new file mode 100644
index 0000000000000000000000000000000000000000..9730d7b91ef22e2b194a32d746f0f00f3916267a
--- /dev/null
+++ b/lms/djangoapps/courseware/tests/test_registration_extra_vars.py
@@ -0,0 +1,151 @@
+# -*- coding: utf-8
+"""
+Tests for extra registration variables
+"""
+import json
+import uuid
+
+from django.conf import settings
+from django.core.urlresolvers import reverse
+from mock import patch
+
+from courseware.tests.helpers import LoginEnrollmentTestCase, check_for_post_code
+
+
+class TestExtraRegistrationVariables(LoginEnrollmentTestCase):
+    """
+    Test that extra registration variables are properly checked according to settings
+    """
+
+    def _do_register_attempt(self, **extra_fields_values):
+        """
+        Helper method to make the call to the do registration
+        """
+        username = 'foo_bar' + uuid.uuid4().hex
+        fields_values = {
+            'username': username,
+            'email': 'foo' + uuid.uuid4().hex + '@bar.com',
+            'password': 'password',
+            'name': username,
+            'terms_of_service': 'true',
+        }
+        fields_values = dict(fields_values.items() + extra_fields_values.items())
+        resp = check_for_post_code(self, 200, reverse('create_account'), fields_values)
+        data = json.loads(resp.content)
+        return data
+
+    def test_default_missing_honor(self):
+        """
+        By default, the honor code must be required
+        """
+        data = self._do_register_attempt(honor_code='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'To enroll, you must follow the honor code.')
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'honor_code': 'optional'})
+    def test_optional_honor(self):
+        """
+        With the honor code is made optional, should pass without extra vars
+        """
+        data = self._do_register_attempt(honor_code='')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {
+        'level_of_education': 'hidden',
+        'gender': 'hidden',
+        'year_of_birth': 'hidden',
+        'mailing_address': 'hidden',
+        'goals': 'hidden',
+        'honor_code': 'hidden',
+        'city': 'hidden',
+        'country': 'hidden'})
+    def test_all_hidden(self):
+        """
+        When the fields are all hidden, should pass without extra vars
+        """
+        data = self._do_register_attempt()
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'city': 'required'})
+    def test_required_city_missing(self):
+        """
+        Should require the city if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', city='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'A city is required')
+
+        data = self._do_register_attempt(honor_code='true', city='New York')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'country': 'required'})
+    def test_required_country_missing(self):
+        """
+        Should require the country if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', country='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'A country is required')
+
+        data = self._do_register_attempt(honor_code='true', country='New York')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'level_of_education': 'required'})
+    def test_required_level_of_education_missing(self):
+        """
+        Should require the level_of_education if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', level_of_education='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'A level of education is required.')
+
+        data = self._do_register_attempt(honor_code='true', level_of_education='p')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'gender': 'required'})
+    def test_required_gender_missing(self):
+        """
+        Should require the gender if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', gender='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'Your gender is required')
+
+        data = self._do_register_attempt(honor_code='true', gender='m')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'year_of_birth': 'required'})
+    def test_required_year_of_birth_missing(self):
+        """
+        Should require the year_of_birth if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', year_of_birth='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'Your year of birth is required')
+
+        data = self._do_register_attempt(honor_code='true', year_of_birth='1982')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'mailing_address': 'required'})
+    def test_required_mailing_address_missing(self):
+        """
+        Should require the mailing_address if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', mailing_address='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'Your mailing address is required')
+
+        data = self._do_register_attempt(honor_code='true', mailing_address='my address')
+        self.assertEqual(data['success'], True)
+
+    @patch.dict(settings.REGISTRATION_EXTRA_FIELDS, {'goals': 'required'})
+    def test_required_goals_missing(self):
+        """
+        Should require the goals if configured as 'required' but missing
+        """
+        data = self._do_register_attempt(honor_code='true', goals='')
+        self.assertEqual(data['success'], False)
+        self.assertEqual(data['value'], u'A description of your goals is required')
+
+        data = self._do_register_attempt(honor_code='true', goals='my goals')
+        self.assertEqual(data['success'], True)
diff --git a/lms/envs/aws.py b/lms/envs/aws.py
index 0f1873e6881ca3cf52256fa3a5a67bf8fd239b76..10ba3d70bb9acf6ffe39ead82f293eca0325f687 100644
--- a/lms/envs/aws.py
+++ b/lms/envs/aws.py
@@ -139,7 +139,7 @@ EMAIL_USE_TLS = ENV_TOKENS.get('EMAIL_USE_TLS', False)  # django default is Fals
 SITE_NAME = ENV_TOKENS['SITE_NAME']
 SESSION_ENGINE = ENV_TOKENS.get('SESSION_ENGINE', SESSION_ENGINE)
 SESSION_COOKIE_DOMAIN = ENV_TOKENS.get('SESSION_COOKIE_DOMAIN')
-REGISTRATION_OPTIONAL_FIELDS = ENV_TOKENS.get('REGISTRATION_OPTIONAL_FIELDS', REGISTRATION_OPTIONAL_FIELDS)
+REGISTRATION_EXTRA_FIELDS = ENV_TOKENS.get('REGISTRATION_EXTRA_FIELDS', REGISTRATION_EXTRA_FIELDS)
 
 CMS_BASE = ENV_TOKENS.get('CMS_BASE', 'studio.edx.org')
 
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 9d9ef2559132776f7c9fad3ec3e31cd0746e9a4e..68b4d8b18b910e3d116a00422461c17bbcffd769 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -1153,14 +1153,21 @@ if FEATURES.get('AUTH_USE_CAS'):
 
 ###################### Registration ##################################
 
-# Remove some of the fields from the list to not display them
-REGISTRATION_OPTIONAL_FIELDS = set([
-    'level_of_education',
-    'gender',
-    'year_of_birth',
-    'mailing_address',
-    'goals',
-])
+# For each of the fields, give one of the following values:
+# - 'required': to display the field, and make it mandatory
+# - 'optional': to display the field, and make it non-mandatory
+# - 'hidden': to not display the field
+
+REGISTRATION_EXTRA_FIELDS = {
+    'level_of_education': 'optional',
+    'gender': 'optional',
+    'year_of_birth': 'optional',
+    'mailing_address': 'optional',
+    'goals': 'optional',
+    'honor_code': 'required',
+    'city': 'hidden',
+    'country': 'hidden',
+}
 
 ###################### Grade Downloads ######################
 GRADES_DOWNLOAD_ROUTING_KEY = HIGH_MEM_QUEUE
diff --git a/lms/templates/register.html b/lms/templates/register.html
index ecd819feed150ca2e799bdc693177b978a5f84da..a04ed02f9754d92b73f86730c9bc438063e9cd5b 100644
--- a/lms/templates/register.html
+++ b/lms/templates/register.html
@@ -184,14 +184,33 @@
       </div>
 
       <div class="group group-form group-form-secondary group-form-personalinformation">
-        <h2 class="sr">${_("Optional Personal Information")}</h2>
+        <h2 class="sr">${_("Extra Personal Information")}</h2>
 
         <ol class="list-input">
-          % if 'level_of_education' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['city'] != 'hidden':
+          <li class="field ${settings.REGISTRATION_EXTRA_FIELDS['city']} text" id="field-city">
+            <label for="city">${_('City')}</label>
+            <input id="city" type="text" name="city" value="" placeholder="${_('example: New York')}" aria-describedby="city-tip" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['city'] == 'required' else ''} />
+          </li>
+          % endif
+          % if settings.REGISTRATION_EXTRA_FIELDS['country'] != 'hidden':
+          <li class="field-group">
+          <div class="field ${settings.REGISTRATION_EXTRA_FIELDS['country']} select" id="field-country">
+              <label for="country">${_("Country")}</label>
+              <select id="country" name="country" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['country'] == 'required' else ''}>
+                <option value="">--</option>
+                %for code, country_name in COUNTRIES:
+                <option value="${code}">${ unicode(country_name) }</option>
+                %endfor
+              </select>
+            </div>
+          </li>
+          % endif
+          % if settings.REGISTRATION_EXTRA_FIELDS['level_of_education'] != 'hidden':
           <li class="field-group">
-            <div class="field select" id="field-education-level">
+          <div class="field ${settings.REGISTRATION_EXTRA_FIELDS['level_of_education']} select" id="field-education-level">
               <label for="education-level">${_("Highest Level of Education Completed")}</label>
-              <select id="education-level" name="level_of_education">
+              <select id="education-level" name="level_of_education" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['level_of_education'] == 'required' else ''}>
                 <option value="">--</option>
                 %for code, ed_level in UserProfile.LEVEL_OF_EDUCATION_CHOICES:
                 <option value="${code}">${ed_level}</option>
@@ -200,11 +219,11 @@
             </div>
           </li>
           % endif
-          % if 'gender' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['gender'] != 'hidden':
           <li class="field-group">
-            <div class="field select" id="field-gender">
+            <div class="field ${settings.REGISTRATION_EXTRA_FIELDS['gender']} select" id="field-gender">
               <label for="gender">${_("Gender")}</label>
-              <select id="gender" name="gender">
+              <select id="gender" name="gender" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['gender'] == 'required' else ''}>
                 <option value="">--</option>
                 %for code, gender in UserProfile.GENDER_CHOICES:
                 <option value="${code}">${gender}</option>
@@ -213,11 +232,11 @@
             </div>
           </li>
           % endif
-          % if 'year_of_birth' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['year_of_birth'] != 'hidden':
           <li class="field-group">
-            <div class="field select" id="field-yob">
+            <div class="field ${settings.REGISTRATION_EXTRA_FIELDS['year_of_birth']} select" id="field-yob">
               <label for="yob">${_("Year of Birth")}</label>
-              <select id="yob" name="year_of_birth">
+              <select id="yob" name="year_of_birth" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['year_of_birth'] == 'required' else ''}>
                 <option value="">--</option>
                 %for year in UserProfile.VALID_YEARS:
                 <option value="${year}">${year}</option>
@@ -230,20 +249,20 @@
       </div>
 
       <div class="group group-form group-form-personalinformation2">
-        <h2 class="sr">${_("Optional Personal Information")}</h2>
+        <h2 class="sr">${_("Extra Personal Information")}</h2>
 
         <ol class="list-input">
-          % if 'mailing_address' in settings.REGISTRATION_OPTIONAL_FIELDS:
-          <li class="field text" id="field-address-mailing">
+          % if settings.REGISTRATION_EXTRA_FIELDS['mailing_address'] != 'hidden':
+          <li class="field ${settings.REGISTRATION_EXTRA_FIELDS['mailing_address']} text" id="field-address-mailing">
             <label for="address-mailing">${_("Mailing Address")}</label>
-            <textarea id="address-mailing" name="mailing_address" value=""></textarea>
+            <textarea id="address-mailing" name="mailing_address" value="" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['mailing_address'] == 'required' else ''}></textarea>
           </li>
           % endif
 
-          % if 'goals' in settings.REGISTRATION_OPTIONAL_FIELDS:
-          <li class="field text" id="field-goals">
+          % if settings.REGISTRATION_EXTRA_FIELDS['goals'] != 'hidden':
+          <li class="field ${settings.REGISTRATION_EXTRA_FIELDS['goals']} text" id="field-goals">
             <label for="goals">${_("Please share with us your reasons for registering with {platform_name}").format(platform_name=platform_name)}</label>
-            <textarea id="goals" name="goals" value=""></textarea>
+            <textarea id="goals" name="goals" value="" ${'required aria-required="true"' if settings.REGISTRATION_EXTRA_FIELDS['goals'] == 'required' else ''}></textarea>
           </li>
           % endif
         </ol>
@@ -256,17 +275,16 @@
           <li class="field-group">
 
             % if has_extauth_info is UNDEFINED or ask_for_tos :
-
             <div class="field required checkbox" id="field-tos">
               <input id="tos-yes" type="checkbox" name="terms_of_service" value="true" required aria-required="true" />
               <label for="tos-yes">${_('I agree to the {link_start}Terms of Service{link_end}').format(
                 link_start='<a href="{url}" class="new-vp">'.format(url=marketing_link('TOS')),
                 link_end='</a>')}</label>
             </div>
-
             % endif
 
-            <div class="field required checkbox" id="field-honorcode">
+            % if settings.REGISTRATION_EXTRA_FIELDS['honor_code'] != 'hidden':
+            <div class="field ${settings.REGISTRATION_EXTRA_FIELDS['honor_code']} checkbox" id="field-honorcode">
               <input id="honorcode-yes" type="checkbox" name="honor_code" value="true" />
               <%
                 ## TODO: provide a better way to override these links
@@ -279,6 +297,7 @@
                 link_start='<a href="{url}" class="new-vp">'.format(url=honor_code_path),
                 link_end='</a>')}</label>
             </div>
+            % endif
           </li>
         </ol>
       </div>
diff --git a/lms/templates/signup_modal.html b/lms/templates/signup_modal.html
index 345ce8bbf9b4e9b79bc51c6fa244c0910267fd25..4f74523af7e67fe5bd7e66dc5ed06889092bbc7d 100644
--- a/lms/templates/signup_modal.html
+++ b/lms/templates/signup_modal.html
@@ -59,7 +59,7 @@
 
         <div class="input-group">
 
-          % if 'level_of_education' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['level_of_education'] != 'hidden':
           <section class="citizenship">
             <label data-field="level_of_education" for="signup_ed_level">${_("Ed. Completed")}</label>
             <div class="input-wrapper">
@@ -73,7 +73,7 @@
           </section>
           % endif
 
-          % if 'gender' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['gender'] != 'hidden':
           <section class="gender">
             <label data-field="gender" for="signup_gender">${_("Gender")}</label>
             <div class="input-wrapper">
@@ -87,7 +87,7 @@
           </section>
           % endif
 
-          % if 'year_of_birth' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['year_of_birth'] != 'hidden':
           <section class="date-of-birth">
             <label data-field="date-of-birth" for="signup_birth_year">${_("Year of birth")}</label>
             <div class="input-wrapper">
@@ -102,12 +102,12 @@
           </section>
           % endif
 
-          % if 'mailing_address' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['mailing_address'] != 'hidden':
           <label data-field="mailing_address" for="signup_mailing_address">${_("Mailing address")}</label>
 	    <textarea id="signup_mailing_address" name="mailing_address"></textarea>
           % endif
 
-          % if 'goals' in settings.REGISTRATION_OPTIONAL_FIELDS:
+          % if settings.REGISTRATION_EXTRA_FIELDS['goals'] != 'hidden':
           <label data-field="goals" for="signup_goals">${_("Goals in signing up for {platform_name}").format(platform_name=settings.PLATFORM_NAME)}</label>
 	    <textarea name="goals" id="signup_goals"></textarea>
           % endif
@@ -122,12 +122,14 @@
               link_end='</a>')}
           </label>
 
+          % if settings.REGISTRATION_EXTRA_FIELDS['honor_code'] != 'hidden':
           <label data-field="honor_code" class="honor-code" for="signup_honor">
             <input id="signup_honor" name="honor_code" type="checkbox" value="true">
             ${_('I agree to the {link_start}Honor Code{link_end}*').format(
               link_start='<a href="{url}" target="_blank">'.format(url=reverse('honor')),
               link_end='</a>')}
           </label>
+          % endif
         </div>
 
         <div class="submit">