… Login saleor with other social media
... social-auth-app-django
I've gone through the code base and found that social-auth-app-django and relevant stuff were gradually phased out
Why is that? Could we re-enable it?
By the way, detail setup, step by step document will be better (Reading the doc front and back, found no detail setup tutorials)
I'm using social-auth-app-django and it's quite easy to setup, however, OAuth-flow doesn't easy to work with stateless graphql in my opinion because it's designed to work with session for the WEB.
https://github.com/python-social-auth/social-app-django/blob/b5a6434cb7dd308debc694f94753398a15445580/social_django/views.py#L103
For a scenario that mobile applications will use an SDK to signup a user within the app, I'd tried integrate social-auth-app-django into saleor's api. Here is the code.
import graphene
from functools import wraps
from django.contrib.auth import authenticate, get_user_model
from django.utils.translation import ugettext as _
from promise import Promise, is_thenable
from django.dispatch import Signal
token_issued = Signal(providing_args=['request', 'user'])
from graphql_jwt.exceptions import JSONWebTokenError, PermissionDenied
from graphql_jwt.mixins import ResolveMixin, ObtainJSONWebTokenMixin
from graphql_jwt.decorators import setup_jwt_cookie
from graphql_jwt.settings import jwt_settings
from graphql_jwt.shortcuts import get_token
from graphql_jwt.refresh_token.shortcuts import refresh_token_lazy
from social_django.utils import load_strategy, load_backend
from social_django.compat import reverse
from ..account.types import User
from ..core.types import Error
def token_auth(f):
@wraps(f)
@setup_jwt_cookie
def wrapper(cls, root, info, **kwargs):
context = info.context
context._jwt_token_auth = True
def on_resolve(values):
user, payload = values
payload.token = get_token(user, context)
if jwt_settings.JWT_LONG_RUNNING_REFRESH_TOKEN:
payload.refresh_token = refresh_token_lazy(user)
return payload
token = kwargs.get('access_token')
backend = kwargs.get('backend')
context.social_strategy = load_strategy(context)
# backward compatibility in attribute name, only if not already
# defined
if not hasattr(context, 'strategy'):
context.strategy = context.social_strategy
uri = reverse('social:complete', args=(backend,))
context.backend = load_backend(context.social_strategy, backend, uri)
user = context.backend.do_auth(token)
if user is None:
raise JSONWebTokenError(
_('Please, enter valid credentials'))
if hasattr(context, 'user'):
context.user = user
result = f(cls, root, info, **kwargs)
values = (user, result)
token_issued.send(sender=cls, request=context, user=user)
if is_thenable(result):
return Promise.resolve(values).then(on_resolve)
return on_resolve(values)
return wrapper
class JSONWebTokenMutation(ObtainJSONWebTokenMixin, graphene.Mutation):
class Meta:
abstract = True
@classmethod
@token_auth
def mutate(cls, root, info, **kwargs):
return cls.resolve(root, info, **kwargs)
class CreateOAuthToken(ResolveMixin, JSONWebTokenMutation):
errors = graphene.List(Error, required=True)
user = graphene.Field(User)
class Arguments:
access_token = graphene.String(description="Access token.")
backend = graphene.String(description="Authenticate backend")
@classmethod
def mutate(cls, root, info, **kwargs):
try:
result = super().mutate(root, info, **kwargs)
except JSONWebTokenError as e:
return CreateOAuthToken(errors=[Error(message=str(e))])
else:
return result
@classmethod
def resolve(cls, root, info, **kwargs):
return cls(user=info.context.user, errors=[])
class OAuthMutations(graphene.ObjectType):
oauth_token_create = CreateOAuthToken.Field()
And schema.graphql
type Mutation {
...
oauthTokenCreate(backend: String!, access_token: String!): CreateOAuthToken
...
}
settings.py
INSTALLED_APPS = [
"social_django",
...
]
AUTHENTICATION_BACKENDS = [
"social_core.backends.google.GoogleOAuth2", # <-
"graphql_jwt.backends.JSONWebTokenBackend",
"django.contrib.auth.backends.ModelBackend",
]
# social-auth
SOCIAL_AUTH_POSTGRES_JSONFIELD = True
SOCIAL_AUTH_URL_NAMESPACE = 'social'
SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details',
'social_core.pipeline.social_auth.social_uid',
'social_core.pipeline.social_auth.social_user',
'social_core.pipeline.user.get_username',
'social_core.pipeline.user.create_user',
'social_core.pipeline.social_auth.associate_user',
'social_core.pipeline.social_auth.load_extra_data',
'social_core.pipeline.user.user_details',
'social_core.pipeline.social_auth.associate_by_email',
)
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'INSERT_PROVIDED_KEY_HERE'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'INSERT_PROVIDED_SECRET_HERE'
iframe and postMessage to get access_tokenoauthTokenCreate with that access_token@ace-han Hey! Currently, login via social media is not available. @gsoec has provided a good solution how to setup the social media login by yourself. If you have more questions just let me know.
@karolkielecki I think email as username some kind of making it harder to integrate with OAuth login (some would be phone number or just don't have an email field)
I think this feature is needed since most start-ups are not mighty enough to host brand-new email(user) registration
I tried using this method but didn't work for me.
Most helpful comment
I'm using
social-auth-app-djangoand it's quite easy to setup, however, OAuth-flow doesn't easy to work with stateless graphql in my opinion because it's designed to work withsessionfor the WEB.https://github.com/python-social-auth/social-app-django/blob/b5a6434cb7dd308debc694f94753398a15445580/social_django/views.py#L103
For a scenario that mobile applications will use an SDK to signup a user within the app, I'd tried integrate
social-auth-app-djangointo saleor's api. Here is the code.And schema.graphql
settings.pySolution for SPA
iframeandpostMessageto getaccess_tokenoauthTokenCreatewith thataccess_tokenAssisted Token Flow: https://tools.ietf.org/id/draft-ideskog-assisted-token-00.html