OAuth Help

629 views
Skip to first unread message

ErikT

unread,
Mar 16, 2017, 2:49:33 PM3/16/17
to airbnb_superset
Hello,

Has anyone implemented OAuth with superset? I feel like I'm very close and need help with the last mile.

I'm allowed to register my Oauth'd user in Superset. After the user has been created receive a return code from the github auth exchange (e.g. http://192.168.99.100:8088/oauth-authorized/github?code=073d9e936d7270013703). However when i'm returned to the /login page, I receive a message "Invalid login. Please try again." message after the exchange.

I've pored over the flask-appbuiler docs.

    import os
    from flask_appbuilder.security.manager import AUTH_OAUTH

    MAPBOX_API_KEY = os.getenv('MAPBOX_API_KEY', '')
    CACHE_CONFIG = {
            'CACHE_TYPE': 'redis',
            'CACHE_DEFAULT_TIMEOUT': 300,
            'CACHE_KEY_PREFIX': 'superset_',
            'CACHE_REDIS_HOST': 'redis',
            'CACHE_REDIS_PORT': 6379,
            'CACHE_REDIS_DB': 1,
            'CACHE_REDIS_URL': 'redis://redis-service:6379/1'}
    SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://postgres-service:5432'
    SECRET_KEY = 'thisISaSECRET_1234'
    AUTH_TYPE = AUTH_OAUTH
    CSRF_ENABLED = False
    TESTING = True
    WTF_CSRF_ENABLED = False
    RECAPTCHA_USE_SSL = False
    RECAPTCHA_PUBLIC_KEY = ''
    RECAPTCHA_PRIVATE_KEY = ''

    MAIL_SERVER = 'mail.com'
    MAIL_USE_TLS = False
    MAIL_USERNAME = 'te...@mail.com'
    MAIL_PASSWORD = 'test'
    MAIL_DEFAULT_SENDER = 'supe...@mail.com'

    USER_ENABLE_LOGIN_WITHOUT_CONFIRM_EMAIL = True
    USER_ENABLE_CONFIRM_EMAIL = False
    EMAIL_NOTIFICATIONS = False
    DEBUG = True

    # Will allow user self registration
    AUTH_USER_REGISTRATION = True

    # The default user self registration role
    AUTH_USER_REGISTRATION_ROLE = 'Admin'

    OAUTH_PROVIDERS = [
        {'name':'github', 'icon':'fa-github', 'token_key':'access_token',
            'remote_app': {
                'consumer_key':'GIT CLIENT ID',
                'consumer_secret':'GIT CLIENT SECRET',
                'base_url':'https://github.enterprise.com/api/v3/user',
                'request_token_params':{'scope': 'user:email'},
                'request_token_url':None,
                'access_token_url':'https://github.enterprise.com/login/oauth/access_token',
                'authorize_url':'https://github.enterprise.com/login/oauth/authorize'}
        }
      ]

Do i need to override the oauth_user_info_getter method? what would that look like in the superset_config.py file?

Thank you very much! Have really enjoined the tool.

PS: I'm using a slightly modified container as the 0.17.0 version I've just rebuilt it with the additional flask modules needed for oauth.

Erik

Christian Windolf

unread,
Mar 22, 2017, 10:42:25 AM3/22/17
to airbnb_superset
Hi Erik,

Unfortunately, after retrieving a valid access token from the oauth server, every flash error message is "
Invalid login. Please try again." No matter what what goes wrong exactly. :(

in principle it should not be necessary to override this method, as there is already a handler in the source code for github (but I haven't tried it out...) So I am quite sure, you do not need to override this.

If you want to implement your own method, you can just set the CUSTOM_SECURITY_MANAGER variable in the superset_config.py to your own security manager.

Override the oauth_user_info method there. :)

But I think, it is the auth_user_oauth method, that you want to override. After retrieving the user_info from the oauth server (and converting it into a Python dict),
this method is called. It is supposed to return a user model object.
The default implementation expects, that there is a user with a matching username in the database.


Christian

ErikT

unread,
Mar 22, 2017, 12:57:01 PM3/22/17
to airbnb_superset
Hi Christian,

I did end up getting this working. My OAUTH setup was just fine. It was the other parts of the security form and user registration that were hanging up the process.

So like you mentioned, we used a custom_security_manager to disable the recaptcha part in the security form and then re-enable email activation. I had be testing this in a local docker / minikube environment and couldn't register a domain with recaptcha so i turned the TESTING env to True. This then caused activation emails to become disabled and thus users getting stuck in the registration table of the superset db.

Here's what the code looks like for the custom security manager as well as the imports to get it working.

    # The code below is used to override the registration view for oauth so it doesn't require recaptcha
    # If modifying do not attempt to import flask.ext.appbuilder and modify the instance of appbuilder directly.
    from flask.ext.appbuilder.security.registerviews import RegisterUserOAuthView
    from flask.ext.appbuilder.forms import DynamicForm
    from wtforms import StringField
    from flask_babel import lazy_gettext
    from wtforms.validators import DataRequired, Email
    from flask.ext.appbuilder.fieldwidgets import BS3TextFieldWidget
    from flask_appbuilder.security.sqla.manager import SecurityManager

    # RegisterUserOIDForm from appbuilder.security.forms minus the recaptcha field
    class RegisterUserOIDFormNoRecaptcha(DynamicForm):
      username = StringField(lazy_gettext('User Name'), validators=[DataRequired()], widget=BS3TextFieldWidget())
      first_name = StringField(lazy_gettext('First Name'), validators=[DataRequired()], widget=BS3TextFieldWidget())
      last_name = StringField(lazy_gettext('Last Name'), validators=[DataRequired()], widget=BS3TextFieldWidget())
      email = StringField(lazy_gettext('Email'), validators=[DataRequired(), Email()], widget=BS3TextFieldWidget())

    # Extends the normal RegisterUserOAuthView and just overrides registration form
    class MyRegisterUserOAuthView(RegisterUserOAuthView):
      """
          View for Registering a new user, auth OID mode
      """
      form = RegisterUserOIDFormNoRecaptcha

    # Custom Security manager with out own oauth registraion form
    class MySecurityManager(SecurityManager):
      registeruseroauthview = MyRegisterUserOAuthView

    # Hook in appbuilder to provide our own security manager
    CUSTOM_SECURITY_MANAGER = MySecurityManager

PS: I added these libraries to my version of the superset container. It's working great in minikube!

        flask-oauth==0.12 \
        flask_oauthlib==0.9.3 \
        flask-mail==0.9.1
Reply all
Reply to author
Forward
0 new messages