Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade : Oauth2 Login for OSM #525

Merged
merged 2 commits into from
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion core/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@
)

AUTHENTICATION_BACKENDS = (
"social_core.backends.openstreetmap.OpenStreetMapOAuth",
# "social_core.backends.openstreetmap.OpenStreetMapOAuth",
"social_core.backends.openstreetmap_oauth2.OpenStreetMapOAuth2",
"oauth2_provider.backends.OAuth2Backend",
"social_core.backends.email.EmailAuth",
"social_core.backends.username.UsernameAuth",
Expand Down
85 changes: 45 additions & 40 deletions core/settings/contrib.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,58 +8,63 @@
# Extra installed apps
INSTALLED_APPS += (
# any 3rd party apps
'rest_framework',
'rest_framework_gis',
'rest_framework.authtoken',
'social_django',
"rest_framework",
"rest_framework_gis",
"rest_framework.authtoken",
"social_django",
)

# 3rd party specific app settings
OAUTH2_PROVIDER = {
'ACCESS_TOKEN_EXPIRE_SECONDS': 10 * 365 * 24 * 60 * 60,
"ACCESS_TOKEN_EXPIRE_SECONDS": 10 * 365 * 24 * 60 * 60,
}

REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter'),
'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework.authentication.TokenAuthentication',
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
'rest_framework.authentication.SessionAuthentication',),
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'api.renderers.HOTExportApiRenderer',
"DEFAULT_FILTER_BACKENDS": (
"rest_framework.filters.SearchFilter",
"rest_framework.filters.OrderingFilter",
),
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
'DEFAULT_VERSION': '1.0',
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 20
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication",
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
"rest_framework.authentication.SessionAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
"DEFAULT_RENDERER_CLASSES": (
"rest_framework.renderers.JSONRenderer",
"api.renderers.HOTExportApiRenderer",
),
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.AcceptHeaderVersioning",
"DEFAULT_VERSION": "1.0",
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
"PAGE_SIZE": 20,
}


# OAuth login settings
SOCIAL_AUTH_OPENSTREETMAP_LOGIN_URL = '/osm/login/'
SOCIAL_AUTH_OPENSTREETMAP_KEY = os.getenv('OSM_API_KEY')
SOCIAL_AUTH_OPENSTREETMAP_SECRET = os.getenv('OSM_API_SECRET')
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_LOGIN_ERROR_URL = '/osm/error'
SOCIAL_AUTH_URL_NAMESPACE = 'osm'
SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ['username', 'first_name', 'email']
SOCIAL_AUTH_OPENSTREETMAP_LOGIN_URL = "/osm/login/"
SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_KEY = os.getenv("OSM_API_KEY")
SOCIAL_AUTH_OPENSTREETMAP_OAUTH2_SECRET = os.getenv("OSM_API_SECRET")
SOCIAL_AUTH_LOGIN_REDIRECT_URL = "/"
SOCIAL_AUTH_LOGIN_ERROR_URL = "/osm/error"
SOCIAL_AUTH_URL_NAMESPACE = "osm"
SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ["username", "first_name", "email"]
SOCIAL_AUTH_FORCE_EMAIL_VALIDATION = True
SOCIAL_AUTH_EMAIL_VALIDATION_FUNCTION = 'ui.pipeline.email_validation'
SOCIAL_AUTH_EMAIL_VALIDATION_URL = '/osm/email_verify_sent/'
SOCIAL_AUTH_EMAIL_VALIDATION_FUNCTION = "ui.pipeline.email_validation"
SOCIAL_AUTH_EMAIL_VALIDATION_URL = "/osm/email_verify_sent/"

SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.auth_allowed',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'ui.pipeline.require_email',
'social_core.pipeline.mail.mail_validation',
'social_core.pipeline.social_auth.associate_by_email',
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.debug.debug',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details'
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.auth_allowed",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.user.get_username",
"ui.pipeline.require_email",
"social_core.pipeline.mail.mail_validation",
"social_core.pipeline.social_auth.associate_by_email",
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"social_core.pipeline.debug.debug",
"social_core.pipeline.social_auth.load_extra_data",
"social_core.pipeline.user.user_details",
)
2 changes: 1 addition & 1 deletion ops/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Examples of how to backup and restore the database:
psql exports < export_tool_2023-03-06.pgdump
```

8. Modify the OAuth1 application with your hostname's `redirect_uris`
8. Modify the OAuth2 application with your hostname's `redirect_uris`

### Storage and Environment Variables

Expand Down
6 changes: 3 additions & 3 deletions ops/systemd/export_workers.env
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ EMAIL_HOST_USER=<INSECURE_SMTP_USERNAME>
EMAIL_HOST_PASSWORD=<SECURE_SMTP_PASSWORD>
REPLY_TO_EMAIL=<INSECURE_REPLY_EMAIL>

##OAUTH 1 Settings
OSM_API_KEY=<SECURE_OSM_OAUTH1_APP_CONSUMER_KEY>
OSM_API_SECRET=<SECURE_OSM_OAUTH1_APP_CONSUMER_SECRET>
##OAUTH 2 Settings
OSM_API_KEY=<SECURE_OSM_OAUTH2_APP_CONSUMER_KEY>
OSM_API_SECRET=<SECURE_OSM_OAUTH2_APP_CONSUMER_SECRET>

## Workers
WORKER_SECRET_KEY=<SECURE_WORKER_KEY>
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mercantile~=0.10.0
psycopg2
python3-openid==3.2.0
social-auth-app-django==5.4.0
social-auth-core==4.4.2
social-auth-core==4.4.2 ### Upgrade this to include oauth2
pytz
pyyaml>=5.3
raven
Expand Down
1 change: 1 addition & 0 deletions ui/app/actions/meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ if (window.OAUTH_CLIENT_ID == null) {
}

const oauthConfig = {
// url: window.EXPORTS_API_URL + "/o/openstreetmap_oauth2",
url: window.EXPORTS_API_URL + "/o/authorize?approval_prompt=auto",
client: window.OAUTH_CLIENT_ID,
redirect: `${window.location.protocol}//${hostname}/authorized`
Expand Down
2 changes: 1 addition & 1 deletion ui/app/components/help/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default () =>
<p>User authentication and authorization is a two-step process.</p>
<p>
The Export Tool requires that users log into OpenStreetMap using{" "}
<a href="https://oauth.net/1/">OAuth 1.0a</a> (you don't need to know
<a href="https://oauth.net/2/">OAuth 2.0a</a> (you don't need to know
this). This provides user identity, specifically an OSM username to
associate with exports. You generally don't need to care about this,
except to know that usernames are the same as on OSM.
Expand Down
2 changes: 1 addition & 1 deletion ui/templates/osm/email.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
{% blocktrans %}Please provide a valid email address. This email address will be used to notifiy you when your exports are ready.
A verification link will be sent to the email address you provide.{% endblocktrans %}
<br/><br/>
<form method="post" action="{% url 'osm:complete' 'openstreetmap' %}" id="registerEmail">
<form method="post" action="{% url 'osm:complete' 'openstreetmap-oauth2' %}" id="registerEmail">
{% csrf_token %}
<div class="form-group row" id="form-group-email">
<div class="col-md-12">
Expand Down
7 changes: 4 additions & 3 deletions ui/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def login(request):
if not request.user.is_authenticated:
# preserve redirects ("next" in request.GET)
return redirect(
reverse("osm:begin", args=["openstreetmap"]) + "?" + request.GET.urlencode()
reverse("osm:begin", args=["openstreetmap-oauth2"])
+ "?"
+ request.GET.urlencode()
)
else:
return redirect("/v3/")
Expand All @@ -48,7 +50,7 @@ def v3(request, *args, **kwargs):
except Application.DoesNotExist:
ui_app = Application.objects.create(
name="OSM Export Tool UI",
redirect_uris="http://localhost/authorized http://localhost:8080/authorized http://localhost:8000/authorized",
redirect_uris="http://localhost/authorized http://127.0.0.1:8000/authorized http://localhost:8080/authorized http://localhost:8000/authorized",
client_type=Application.CLIENT_PUBLIC,
authorization_grant_type=Application.GRANT_IMPLICIT,
skip_authorization=True,
Expand All @@ -70,7 +72,6 @@ def redirect_to_v3(request):
def worker_dashboard(request):
if not request.user.is_superuser:
return HttpResponseForbidden()
# return HttpResponse('test')
return HttpResponseRedirect(f"/{settings.WORKER_SECRET_KEY}/")


Expand Down
Loading