Authenticating a Flask API using Okta

Erika Dike
Jul 11 · 11 min read
Photo by Ryan Quintal on Unsplash

Set up Flask API

$ python3 -m venv --prompt='flask-okta' .virtualenv
$ source .virtualenv/bin/activate
Flask>=1.0.0
flask-oidc==1.4.0
okta==0.0.4
from datetime import datetimefrom flask import Flaskapp = Flask(__name__)
@app.route('/')
def index():
return 'Welcome'
@app.route('/greet')
def greet():
time = datetime.now().hour
if time >= 0 and time < 12:
return 'Good Morning!'
elif time >= 12 and time < 16:
return 'Good Afternoon!'
else:
return 'Good Evening!'

Create an OpenID connect application on Okta

Create an Authentication Token

Add Okta Authentication to the Flask Application

Craft your OpenID Connect Configuration File

{
"web": {
"client_id": "{{ OKTA_CLIENT_ID }}",
"client_secret": "{{ OKTA_CLIENT_SECRET }}",
"auth_uri": "{{ OKTA_ORG_URL }}/oauth2/default/v1/authorize",
"token_uri": "{{ OKTA_ORG_URL }}/oauth2/default/v1/token",
"issuer": "{{ OKTA_ORG_URL }}/oauth2/default",
"userinfo_uri": "{{ OKTA_ORG_URL }}/oauth2/default/userinfo",
"redirect_uris": [
"http://localhost:5000/oidc/callback"
]
}
}

Configure Flask-OIDC

from flask import Flask
from flask_oidc import OpenIDConnect
app = Flask(__name__)app.config['OIDC_CLIENT_SECRETS'] = 'client_seecrets.json'
app.config['OIDC_COOKIE_SECURE'] = False
app.config['OIDC_CALLBACK_ROUTE'] = '/oidc/callback'
app.config['OIDC_SCOPES'] = ['openid', 'email', 'profile']
app.config['SECRET_KEY'] = '{{ LONG_RANDOM_STRINGS }}'
oidc = OpenIDConnect(app)

Inject the User into Each Request

from flask import Flask, g
from flask_oidc import OpenIDConnect
from okta import UsersClient
...
app.config['SECRET_KEY'] = '{{ LONG_RANDOM_STRINGS }}'
oidc = OpenIDConnect(app)
okta_client = UsersClient('{{ OKTA_ORG_URL }}', '{{ OKTA_AUTH_TOKEN }}')

@app.before_request
def inject_user_into_each_request()
if oidc.user_loggedin:
g.user = okta_client.get_user(oidc.user_getfield('sub'))
else:
g.user = None

Enable User Login and Logout

...from flask import current_app, Flask, g, redirect, url_for...@app.route('/greet')
@oidc.require_login
def greet():
time = datetime.now().hour
if time >= 0 and time < 12:
return 'Good Morning!'
elif time >= 12 and time < 16:
return 'Good Afternoon!'
else:
return 'Good Evening!'
@app.route('/login')
@oidc.require_login
def login():
return redirect(url_for('.greet'))
@app.route('/logout')
def logout():
oidc.logout()
return redirect(url_for('.index'))

Limiting Access to a Specific Group


The Andela Way

A pool of thoughts from the brilliant people at Andela

Erika Dike

Written by

I write software and occasionally publish stuff about some things I found interesting.

The Andela Way

A pool of thoughts from the brilliant people at Andela