Session and Custom parameters and claims in `password` grant flow
#Overview
So you don't want the login page... you just want to send credentials and get back an SSO cookie. It's the anti-pattern of federated identity, with well-known negative security implications. But you don't care! The product team has their vision of what the login page should look like. The security team has no power to prevent this terrible practice with a semblance of security hygiene, so here we are!
This tutorial offers a step-by-step guide for a basic proof-of-concept environment using the OAuth password grant flow. Refer to general documentation describing each component for more details.
#Testing
- Install CE 4.4
- Log into oxTrust admin GUI
- Enable
resource_owner_password_credentials_custom_params_exampleResource Owner Password Credentials script - Enable
introspection_custom_paramsIntrospection script - Register OpenId client for RO flow with next parameters:
- Grant Types =
password - Authentication method for the Token Endpoint =
client_secret_post
- Grant Types =
- Prepare and run demo RP
- Put into CE
/usr/lib/cgi-binfolder filerp.pywith next content:
- Put into CE
#!/usr/bin/python
# -*- coding: utf-8 -*-
import cgitb
import ssl
import httplib, urllib, urllib2
import json
import sys
import io
import codecs
# Enable detail logging
cgitb.enable()
# Configuration
op_server_uri = "https://<server>"
op_client_id = "<client_id>"
op_client_secret = "<client_secret>"
user_name = "<user_name>"
pwd = "<user_pwd>"
session_id_cookie_domain = ".<domain>"
# Outut should be utf-8
#def enc_print(string='', encoding='utf8'):
# sys.stdout.buffer.write(string.encode(encoding) + b'\n')
# Prepare SSL trust all context
context = ssl._create_unverified_context()
# Get access_token
token_post_params_json = { 'client_id': op_client_id, 'client_secret': op_client_secret,
'username': user_name, 'password': pwd, 'grant_type': 'password',
'custom1': 'custom_value_1', 'custom2': 'custom_value_2' }
post_token_params_url_encoded = urllib.urlencode(token_post_params_json)
token_headers_json = { 'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }
token_endpoint_uri = '%s/oxauth/restv1/token' % op_server_uri
token_req = urllib2.Request(token_endpoint_uri, post_token_params_url_encoded, token_headers_json)
try:
token_resp = urllib2.urlopen(token_req, context=context)
except Exception as e:
print("Content-Type: text/html\n")
print("<title>RP script output</title>")
print("Failed to get access_token!")
exit()
token_resp_data = token_resp.read()
token_resp_json = json.loads(token_resp_data)
access_token = token_resp_json['access_token']
# Request introspection
introspection_post_params_json = { 'token': access_token }
post_introspection_params_url_encoded = urllib.urlencode(introspection_post_params_json)
introspection_headers_json = { 'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json', 'Authorization': 'Bearer %s' % access_token }
introspection_endpoint_uri = '%s/oxauth/restv1/introspection' % op_server_uri
introspection_req = urllib2.Request(introspection_endpoint_uri, post_introspection_params_url_encoded, introspection_headers_json)
try:
introspection_resp = urllib2.urlopen(introspection_req, context=context)
except Exception as e:
print("Content-Type: text/html\n")
print("<title>RP script output</title>")
print("Failed to get introspection data!")
exit()
introspection_resp_data = introspection_resp.read()
introspection_resp_json = json.loads(introspection_resp_data)
session_id = introspection_resp_json['session_id']
print("Content-Type: text/html")
#print("Set-Cookie: session_id=%s; Path=/; Secure; HttpOnly; Expires=Fri, 08 Nov 2030 18:52:39 +0000; HttpOnly" % session_id)
print("Set-Cookie: session_id=%s; domain=%s; Path=/; Secure; HttpOnly; Expires=Fri, 08 Nov 2030 18:52:39 +0000; HttpOnly" % (session_id, session_id_cookie_domain))
print("\n")
print("<title>RP script output</title>")
print("<h1>RP 'password' grant sample application</h1>")
print("<p>Token Response Data:</p>")
print("<pre>" + token_resp_data + "</pre>")
print("<p>Introspection Response Data:</p>")
print("<pre>" + introspection_resp_data + "</pre>")- Update next parameters in file above:
op_server_uri,op_client_id,op_client_secretuser_name,pwdsession_id_cookie_domain - Set executable permission to this file
- Open in browser
https://<server>/cgi-bin/rp.py - As result this demo pge should produce page with
tokenandintrospection responses. Also it should setsession_idcookie
- Open in browser
https://<server>to login to oxTrust. oxAuth should accept cookie whichrp.pyset and allow login to the application without entering credentials.
#Note
- In order to fully support this flow we need to resolve issue: https://github.com/GluuFederation/oxAuth/issues/1196 Without this issue resolution after logout from oxTrust user not able to logging until he restart browser.
