Learn About Authentication Between Python Applications and Oracle Identity Cloud Service
You’re ready to learn about authentication between Python web applications and Oracle Identity Cloud Service. This includes understanding the following:
-
Use cases for using an SDK with a Python application to authenticate with Oracle Identity Cloud Service.
-
The three-legged authentication flow that Oracle Identity Cloud Service supports for the Python SDK
-
Methods and functions of the Python SDK
Learn About Three-Legged Authentication Flows
Oracle Identity Cloud Service supports the three-legged authentication flow for the Python SDK. In this flow, users interact directly with Oracle Identity Cloud Service. After a user signs in, Oracle Identity Cloud Service issues an authorization code that the SDK exchanges for a user access token. This access token can be used by the Python application to grant users access to the protected resources in the application. The three-legged flow uses the authorization code grant type.
For increased security, Oracle recommends that you use three-legged flows to integrate your Python web applications with Oracle Identity Cloud Service for authentication. By using the authorization code grant type, you can also access other applications that are protected by Oracle Identity Cloud Service without having to re-authenticate.
Learn About the Primary Use Cases for Using an SDK with a Python Application
The Python web application implements two use cases: one for authenticating users and the other for accessing detailed information about the user who is logged in.
The following data flow diagrams illustrate the flow of events, calls, and responses between the web browser, the web application, and Oracle Identity Cloud Service for each use case.
The data flow happens this way:
-
The user requests a protected resource.
-
The authentication module uses the SDK to generate a request-authorization-code URL for Oracle Identity Cloud Service and send this URL as a redirect response to the web browser.
-
The web browser calls the URL.
-
The Oracle Identity Cloud Service Sign In page appears.
-
The user submits their Oracle Identity Cloud Service sign-in credentials.
-
After the user logs in successfully, Oracle Identity Cloud Service creates a session for the user and issues an authorization code.
-
The web application makes a back-end (or server-to-server) call to exchange the authorization code for a user access token.
-
Oracle Identity Cloud Service issues an access token and an id token.
-
A session is established, and the user is redirected to the Home page.
-
The Home page of the web application appears.
The data flow happens this way:
-
The user requests the
/myProfile
resource. -
The web application uses Oracle Identity Cloud Service's SDK to validate the id token.
-
The data that returns from id token validation contains user's details in the format of a JSON object.
-
The My Profile page renders the JSON object as HTML content.
Learn About Methods and Functions of the Python SDK
The Python SDK is available as two python files,
IdcsClient.py
and Constants.py
, which you must include
in your web application.
These python files are dependent on third-party libraries that also must be included
in your application. To include them, open the SDK zip file, extract both
README.txt
and requirements.txt
files to a
temporary folder, and run pip install -r requirements.txt
command.
A sample web application was developed by using the Python DJango framework, which implements URL routes in the form of functions.
The Python SDK requires a JSON variable that’s loaded with Oracle Identity Cloud Service connection information. The Python web application uses a
config.json
file that provides the following information.
{ "ClientId" : "123456789abcdefghij", "ClientSecret" : "abcde-12345-zyxvu-98765-qwerty", "BaseUrl" : "https://idcs-abcd1234.identity.oraclecloud.com", "AudienceServiceUrl" : "https://idcs-abcd1234.identity.oraclecloud.com", "scope" : "urn:opc:idm:t.user.me openid", "TokenIssuer" : "https://identity.oraclecloud.com/", "redirectURL": "http://localhost:8000/callback", "logoutSufix":"/oauth2/v1/userlogout", "LogLevel":"INFO", "ConsoleLog":"True" }
Below is a brief explanation of each required attribute for this SDK:
Table - Required Attributes for the Python SDK
Attribute Name | Attribute Description |
---|---|
ClientId |
The value of the client ID that’s generated after you register the web application by using the Oracle Identity Cloud Service console. |
ClientSecret |
The value of the client secret that’s generated after you register the web application using the Oracle Identity Cloud Service console. |
BaseUrl |
The domain URL of your Oracle Identity Cloud Service instance. |
AdminServiceUrl |
The domain name URL of your Oracle Identity Cloud Service instance. This is usually the same as
BaseUrl .
|
TokenIssuer |
Keep the value as presented here. |
scope |
The scope controls the data that the application can access or process on behalf of the user. Because the application uses the SDK for authentication, the scope is openid . The application also implements the get user details use case, for which you must also use the scope urn:opc:idm:t.user.me .
|
ConsoleLog |
Enables SDK log. |
LogLevel |
Indicates the log level of the SDK. |
The logoutSufix
and redirectURL
attributes are both used by the application. Therefore, they aren’t required by the SDK.
The application implements the auth
function definition, which maps
the /auth
URL. When a user authenticates with Oracle Identity Cloud Service, the browser makes a request to this URL.
The auth
function initializes the Authentication Manager, uses the
JSON configuration attributes as parameters, uses the SDK to generate the Oracle Identity Cloud Service authorization code URL, and then redirects the browser to this URL.
#Loading the SDK Python file. from . import IdcsClient #Function used to load the configurations from the config.json file def getOptions(): fo = open("config.json", "r") config = fo.read() options = json.loads(config) return options # Definition of the /auth route def auth(request): #Loading the configurations options = getOptions() print "config.json file = %s" % options #Authentication Manager loaded with the configurations. am = IdcsClient.AuthenticationManager(options) #Using Authentication Manager to generate the Authorization Code URL, passing the #application's callback URL as parameter, along with code value and code parameter. url = am.getAuthorizationCodeUrl(options["redirectURL"], options["scope"], "1234", "code") #Redirecting the browser to the Oracle Identity Cloud Service Authorization URL. return HttpResponseRedirect(url)
The following parameters are used to generate the authorization code URL:
Table - Parameters used to generate the authorization code URL
Parameter Name | Parameter Description |
---|---|
options["redirectURL"] |
After successful sign in, Oracle Identity Cloud Service redirects the user’s web browser to this URL. This URL must match the one that you’ll configure for the trusted application in the Oracle Identity Cloud Service console. |
options["scope"] |
The OAuth or OpenID Connect scope of authentication. This application requires only openid authentication.
|
state |
The web application uses this code to check whether communication can be established to Oracle Identity Cloud Service. The parameter is defined by the OAuth protocol. |
response_type |
The value that is required by the authorization code grant type (for example, code ).
|
The callback
function uses the authorization code URL parameter to
request an access token and an id token. Both tokens are stored in the user session for
future use.
# Definition of the /callback route def callback(request): code = request.GET.get('code') #Authentication Manager loaded with the configurations. am = IdcsClient.AuthenticationManager(getOptions()) #Using the Authentication Manager to exchange the Authorization Code to an Access Token. ar = am.authorizationCode(code) #Get the access token as a variable access_token = ar.getAccessToken() id_token = ar.getIdToken() #Validating id token to acquire information such as UserID, DisplayName, list of groups #and AppRoles assigned to the user id_token_verified = am.verifyIdToken(id_token) displayname = id_token_verified.getDisplayName() #The application then adds these information to the User Session. request.session['access_token'] = access_token request.session['id_token'] = id_token request.session['displayname'] = displayname #Rendering the home page and adding displayname to be printed in the page. return render(request,'sampleapp/home.html', {'displayname': displayname})
The myProfile
function accesses the user's id token, calls the
AuthenticationManager
verifyIdToken
function to retrieve user's information such as name,
groups and applications assigned to the user, as JSON text, and then sends the
information to the myProfile.html
for rendering.
# Definition of the /myProfile route def myProfile(request): #Getting the Access Token value from the session access_token = request.session.get('access_token', 'none') if access_token == 'none': #If the access token isn't present redirects to login page. return render(request, 'sampleapp/login.html') else: #If the access token is present, validates the id token to acquire #information such as UserID, DisplayName, list of groups and AppRoles assigned to the user. #Authentication Manager loaded with the configurations. am = IdcsClient.AuthenticationManager(getOptions()) id_token = request.session.get('id_token', 'none') id_token_verified = am.verifyIdToken(id_token) #Getting the user details in json format. jsonProfile = id_token_verified.getIdToken() #Getting User information to send to the My Profile page. displayname = request.session.get('displayname', 'displayname') #Redenring json to be used in the html page. json_pretty = json.dumps(jsonProfile, sort_keys=True, indent=2) context = { 'displayname': displayname, "json_pretty": json_pretty, } #Rendering the content of the My Profile Page. return render(request, 'sampleapp/myProfile.html', context)
To sign the user out from single-sign-on between the application and Oracle Identity Cloud Service, the Python web application implements the logout
function. This
function clears the user session attributes set before, and then redirects the user to
Oracle Identity Cloud Service's OAuth logout URL. This URL is set up in the config.json
file as
the logoutSufix
parameter.
# Definition of the /logout route def logout(request): #Getting the Access Token value from the session access_token = request.session.get('access_token', 'none') if access_token == 'none': #If the access token isn't present redirects to login page. return render(request, 'sampleapp/login.html') else: options = getOptions() url = options["BaseUrl"] url += options["logoutSufix"] url += '?post_logout_redirect_uri=http%3A//localhost%3A8000&id_token_hint=' url += request.session.get('id_token', 'none') #Clear session attributes del request.session['access_token'] del request.session['id_token'] del request.session['displayname'] #Redirect to Oracle Identity Cloud Service logout URL. return HttpResponseRedirect(url)