Apache superset Unable to login using custom security manager - apache-superset

I am customizing apache superset login using custom security manager, but unable to redirect the welcome page. My code for custom_security_manager.py is;
from flask import redirect, g, flash, request
from superset.security import SupersetSecurityManager
from flask_appbuilder.security.views import UserDBModelView,AuthDBView
from flask_appbuilder.security.views import expose
from flask_appbuilder.security.manager import BaseSecurityManager
from flask_login import login_user, logout_user
class CustomAuthDBView(AuthDBView):
#expose('/login/', methods=['GET', 'POST'])
def login(self):
token = request.args.get('token')
flash(token, 'warning')
if token == 'SOME_TOKEN_VALUE':
user = self.appbuilder.sm.find_user(username=request.args.get('username'))
flash(user, 'warning')
login_user(user, remember=False)
return redirect(self.appbuilder.get_url_for_index)
else:
flash('Unable to auto login', 'warning')
return super(CustomAuthDBView,self).login()
class CustomSecurityManager(SupersetSecurityManager):
authdbview = CustomAuthDBView
def __init__(self, appbuilder):
super(CustomSecurityManager, self).__init__(appbuilder)
I am using below link for login:
http://10.92.123.25:8088/login/?username=admin&token=SOME_TOKEN_VALUE

you have to add next redirect path in your URL.
Example:
http://10.92.123.25:8088/login/?username=admin&token=SOME_TOKEN_VALUE&next=/superset/dashboard/11?standalone=true

Related

Authenticating Django-Website with external Json Web Token

I have the following setup:
Apache Webserver running a Django Frontend Webpage
Application Server running a Django REST Framework
I now have to integrate the the Django Frontend into a 3rd party project which is written in java and angular. The authentication is completely handled by this 3rd party.
Users login over LDAP and create a JWT token.
Is it possible to simply receive the token in Django and authenticate the User after successfully decoding the token? And how would this work with the #login_required decorator when I have protected functions?
Is there some sort of project where I can orient on, or do I have to write all myself?
I use a built-in User model to store usernames. This enables me to login the user when authentication is successful and then use Django functionalities such as #login_requested as you'd normally use them.
Below is a sample code (without the code for REST authentication).
from django.contrib import messages
from django.contrib.auth import login
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.views.decorators.cache import never_cache
#never_cache
def user_login(request):
''' User login '''
if request.user.is_authenticated:
return HttpResponseRedirect(reverse('main:index'))
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# Your code for authentication here
# authenticate = ....
if authenticate:
# Get user // create one if it doesn't exist yet
user, created = User.objects.get_or_create(username=username)
# Login user - #login_required decorator can be used after user has been logged in
login(request, user)
next = request.POST.get('next', '/') if request.POST.get('next') else '/'
return HttpResponseRedirect(next)
else:
messages.warning(request, 'Authentication failed', extra_tags=forgot_password)
return HttpResponseRedirect(reverse('main:login'))
else:
return render(request, 'main/login.html', {})

how can I pass curent_user from flask-security to a pluggable view function?

I have a flask app that uses flask security for authentication. I want to use graphql with graphene to fetch data but I'm having trouble accessing the current_user proxy which is I've always used to resolve requests. graphene only provides a customized pluggable view which is understandable but it can't access the current_user within the context of the app and therefore current_user reverts back to AnonymousUser.
here is some sample code
from flask import Flask, render_template, redirect, request
from flask_security import Security, SQLAlchemySessionUserDatastore, login_required, current_user, login_user
from flask_graphql import GraphQLView
import graphene
from graphene_sqlalchemy import SQLAlchemyConnectionField
from .models import UserModel, RoleModel, Todo, TodoModel
from .pipeline import session
app = Flask(__name__, template_folder="../templates", static_folder="../static")
app.config.from_object('core.pipeline.configs.DevConfig')
user_datastore = SQLAlchemySessionUserDatastore(session, UserModel, RoleModel)
security = Security(app, user_datastore)
#app.route('/')
#login_required
def index(path):
user = current_user
return render_template('index.html')
Main issue in your code is
app.add_url_rule('/graphql', view_func=graphql_view())
Where graphql_view() run during code load without any flask request context.
Please, try this code
class GraphQLViewCurrentUser(GraphQLView):
def get_context(self, request):
context = super().get_context(request)
context.update({'current_user': current_user})
return context
app.add_url_rule(
'/graphql', view_func=GraphQLViewCurrentUser.as_view(
'graphql', schema=schema, context={}, graphiql=True))

Authenticate and login users and opening new page

i have two pages in my Django website: home page and the chatting page!
What i want is when the users clicks "start-chatting" app should Authenticate using the user name then do the login after that open the chatting page.
my files:
home.js:
$('.btn-xl').click(function(){
var uname = ('.message-input').val();
$.ajax({
url : '/LogIIn/',
type : 'POST',
data : { name: uname },});
window.open('http://gadgetron.store/P_chat');
$('.message-input').val(null);
document.getElementById('radio02').checked=false;
document.getElementById('radio01').checked=false;
});
views.py:
from chatbot import settings
from django.shortcuts import render
from django.http import HttpResponse, JsonResponse,HttpResponseRedirect
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate
from django.contrib.auth import login
#csrf_exempt
def P_home(request):
context= locals()
template= 'P_home.html'
return render(request,template,context)
#csrf_exempt
def P_chat(request):
context= locals()
template= 'P_chat.html'
return render(request,template,context)
#csrf_exempt
def LogIIn(request):
name = request.POST.get('name')
password = '!Emoo1989'
user = authenticate(username=name)
login(request, user)
return HttpResponse("OK")
i'm new in the authentication but the code didn't work with me

How to secure Flask-Admin if my only user is going to be the Admin?

I have seen plenty of solutions online, however all of them addressed more complex apps which allow external users to create accounts. In my case the only user will be the admin. How do I secure the /admin routes created by Flask-Admin in an efficient way?
You can use Flask-Login for that. I usually add a route to the AdminIndexView class that handles the login if the user isn't logged in, yet. Otherwise the default admin page will be shown.
from flask import Flask
from flask_login import LoginManager
from flask_admin import Admin
app = Flask(__name__)
login_manager = LoginManager(app)
login_manager.session_protection = 'strong'
login_manager.login_view = 'admin.login'
admin = Admin(app, index_view=MyIndexView())
The definition of MyAdminView can look like this:
from flask_admin import AdminIndexView, expose, helpers
class FlaskyAdminIndexView(AdminIndexView):
#expose('/')
def index(self):
if not login.current_user.is_authenticated:
return redirect(url_for('.login'))
return super(MyAdminIndexView, self).index()
#expose('/login', methods=['GET', 'POST'])
def login(self):
form = LoginForm(request.form)
if helpers.validate_form_on_submit(form):
user = form.get_user()
if user is not None and user.verify_password(form.password.data):
login.login_user(user)
else:
flash('Invalid username or password.')
if login.current_user.is_authenticated:
return redirect(url_for('.index'))
self._template_args['form'] = form
return super(MyAdminIndexView, self).index()
#expose('/logout')
#login_required
def logout(self):
login.logout_user()
return redirect(url_for('.login'))
This integrates Flask-Login unobtrusively in the Flask-Admin interface. You will still need to implement the user and password verification like described in the Flask-Login documentation.
EDIT
To prevent unauthorized access to your admin routes create a ModelView class for each view and add a function is_accessible() with the following code:
def is_accessible(self):
if (not login.current_user.is_active or not
login.current_user.is_authenticated):
return False
return True

DefaultAccountAdapter and DefaultSocialAccountAdapter?

I tried the following to specific different signup flows for users who sign up via social accounts (facebook) and those that sign up via traditional login.
from django.conf import settings
from allauth.account.adapter import DefaultAccountAdapter
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
class NormalAdapter(DefaultSocialAccountAdapter):
def get_login_redirect_url(self, request):
if request.user.last_login == request.user.date_joined:
return 'survey/'
else:
return '/results/'
class CorporateAdapter(DefaultAccountAdapter):
def get_login_redirect_url(self, request):
if request.user.last_login == request.user.date_joined:
return 'corporate/survey/'
else:
return 'corporate/results/'
But even if you log in with facebook, it calls DefaultAccountAdapter's get_login_redirect_url instead of DefaultSocialAccountAdapter's.
Point the all auth plugin to the correct adapter classes! Add the following settings to your django app:
# project/settings.py:
ACCOUNT_ADAPTER = 'python.path.to.your.CorporateAdapter'
SOCIALACCOUNT_ADAPTER ='python.path.to.your.NormalAdapter'
Then save and reload the app (if you are on apache, just restart apache)