Skip to content

Commit

Permalink
Merge pull request #2079 from botisan-ai/okta-login
Browse files Browse the repository at this point in the history
Added Okta Login for newer versions of Doccano
  • Loading branch information
Hironsan authored Dec 9, 2022
2 parents 0ea0400 + d6f304b commit a2918f7
Show file tree
Hide file tree
Showing 21 changed files with 146 additions and 8 deletions.
10 changes: 10 additions & 0 deletions backend/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@
"allauth",
"allauth.account",
"allauth.socialaccount",
"allauth.socialaccount.providers.okta",
"dj_rest_auth",
"dj_rest_auth.registration",
"django.contrib.sites",
"django_celery_results",
"django_drf_filepond",
"health_check",
Expand Down Expand Up @@ -280,3 +282,11 @@
CELERY_RESULT_SERIALIZER = "json"

DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

SOCIALACCOUNT_PROVIDERS = {
"okta": {
"OKTA_BASE_URL": env("OAUTH_OKTA_OAUTH2_API_URL", ""),
"OAUTH_PKCE_ENABLED": True,
"APP": {"client_id": env("OAUTH_OKTA_OAUTH2_KEY", ""), "secret": env("OAUTH_OKTA_OAUTH2_SECRET", "")},
}
}
2 changes: 2 additions & 0 deletions backend/config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
urlpatterns += [
path("admin/", admin.site.urls),
path("api-auth/", include("rest_framework.urls")),
path("social/", include("social.urls")),
path("v1/social/", include("social.v1_urls")),
path("v1/health/", include("health_check.urls")),
path("v1/", include("api.urls")),
path("v1/", include("roles.urls")),
Expand Down
6 changes: 4 additions & 2 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ known_first_party = [
"metrics",
"projects",
"roles",
"users"
"users",
"social"
]
known_local_folder = [
"api",
Expand All @@ -140,7 +141,8 @@ known_local_folder = [
"metrics",
"projects",
"roles",
"users"
"users",
"social"
]

[tool.taskipy.tasks]
Expand Down
Empty file added backend/social/__init__.py
Empty file.
Empty file added backend/social/admin.py
Empty file.
6 changes: 6 additions & 0 deletions backend/social/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class SocialConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "social"
Empty file added backend/social/models.py
Empty file.
9 changes: 9 additions & 0 deletions backend/social/okta.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
from allauth.socialaccount.providers.okta.views import OktaOAuth2Adapter
from dj_rest_auth.registration.views import SocialLoginView


class OktaLogin(SocialLoginView):
adapter_class = OktaOAuth2Adapter
callback_url = "/projects"
client_class = OAuth2Client
7 changes: 7 additions & 0 deletions backend/social/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from .okta import OktaLogin

urlpatterns = [
path("complete/okta-oauth2/", OktaLogin.as_view(), name="okta_login"),
]
7 changes: 7 additions & 0 deletions backend/social/v1_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.urls import path

from .views import Social

urlpatterns = [
path("links/", Social.as_view()),
]
26 changes: 26 additions & 0 deletions backend/social/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django.conf import settings
from rest_framework.response import Response
from rest_framework.views import APIView


class Social(APIView):
permission_classes = ()

def get(self, request, *args, **kwargs):
return Response(
{
"okta": {
"type": "oauth2",
"base_url": settings.SOCIALACCOUNT_PROVIDERS.get("okta").get("OKTA_BASE_URL"),
"client_id": settings.SOCIALACCOUNT_PROVIDERS.get("okta").get("APP").get("client_id"),
"redirect_path": "/social/complete/okta-oauth2",
"authorize_url": "https://"
+ settings.SOCIALACCOUNT_PROVIDERS.get("okta").get("OKTA_BASE_URL")
+ "/oauth2/v1/authorize?response_type=code&client_id="
+ settings.SOCIALACCOUNT_PROVIDERS.get("okta").get("APP").get("client_id")
+ "&scope=openid&state=unknown&response_mode=form_post",
}
if settings.SOCIALACCOUNT_PROVIDERS.get("okta").get("OKTA_BASE_URL")
else {},
}
)
46 changes: 46 additions & 0 deletions frontend/components/auth/SocialLogin.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<div>
<v-btn
v-for="item in social"
:key="item.provider"
block
elevation="2"
color="secondary"
:href="item.href"
class="mt-5"
>
{{ $t('user.socialLogin', { provider: item.provider }) }}
</v-btn>
</div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
props: {
fetchSocialLink: {
type: Function,
default: () => Promise
}
},
data() {
return {
social: {}
}
},
async mounted() {
const response = await this.fetchSocialLink()
this.social = Object.entries(response)
.map(([key, value]: any) => ({
provider: key,
value
}))
.filter((item) => !!item.value?.authorize_url)
.map((item: any) => ({
...item,
href: `${item.value.authorize_url}&redirect_uri=${location.origin}${item.value.redirect_path}`
}))
}
})
</script>
2 changes: 2 additions & 0 deletions frontend/domain/models/auth/authRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export interface AuthRepository {
login(username: string, password: string): Promise<void>

logout(): Promise<void>

socialLink(): Promise<any[]>
}
3 changes: 2 additions & 1 deletion frontend/i18n/de/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export default {
login: 'Einloggen',
signOut: 'Ausloggen',
username: 'Benutzername',
password: 'Passwort'
password: 'Passwort',
socialLogin: 'Anmeldung über {provider}'
}
3 changes: 2 additions & 1 deletion frontend/i18n/en/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export default {
login: 'Login',
signOut: 'Sign Out',
username: 'Username',
password: 'Password'
password: 'Password',
socialLogin: 'Login With {provider}'
}
3 changes: 2 additions & 1 deletion frontend/i18n/fr/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export default {
login: 'Connexion',
signOut: 'Déconnexion',
username: "Nom d'utilisateur",
password: 'Mot de passe'
password: 'Mot de passe',
socialLogin: 'Connexion via {provider}'
}
3 changes: 2 additions & 1 deletion frontend/i18n/zh/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export default {
login: '登录',
signOut: '注销',
username: '用户名',
password: '密码'
password: '密码',
socialLogin: '通过 {provider} 登录'
}
8 changes: 6 additions & 2 deletions frontend/pages/auth.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<form-login :login="authenticateUser" />

<social-login :fetch-social-link="fetchSocialLink" />
</v-col>
</v-row>
</v-container>
Expand All @@ -16,14 +18,16 @@
import Vue from 'vue'
import { mapActions } from 'vuex'
import FormLogin from '@/components/auth/FormLogin.vue'
import SocialLogin from '@/components/auth/SocialLogin.vue'
export default Vue.extend({
components: {
FormLogin
FormLogin,
SocialLogin
},
methods: {
...mapActions('auth', ['authenticateUser'])
...mapActions('auth', ['authenticateUser', 'fetchSocialLink'])
}
})
</script>
6 changes: 6 additions & 0 deletions frontend/repositories/auth/apiAuthRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ export class APIAuthRepository implements AuthRepository {
const url = '/auth/logout/'
await this.request.post(url)
}

async socialLink(): Promise<any[]> {
const url = '/social/links/'
const response = await this.request.get(url)
return response.data
}
}
4 changes: 4 additions & 0 deletions frontend/services/application/auth/authApplicationService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ export class AuthApplicationService {
public async logout() {
await this.repository.logout()
}

public async socialLink() {
return await this.repository.socialLink()
}
}
3 changes: 3 additions & 0 deletions frontend/store/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export const actions = {
throw new Error('The credential is invalid')
}
},
async fetchSocialLink() {
return await this.$services.auth.socialLink()
},
async initAuth({ commit }) {
try {
const user = await this.$services.user.getMyProfile()
Expand Down

0 comments on commit a2918f7

Please sign in to comment.