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 reauthenticate.
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 the access 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 calls Oracle Identity Cloud Service using the SDK, which uses the access token that’s stored in the user session as a parameter.
-
The user's details are sent to the web application as 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, run the following pip install
commands:
pip install simplejson==3.13.2 pip install cryptography==2.1.4 pip install PyJWT==1.5.2 pip install requests==2.18.4 pip install six==1.10.0 pip install py3_lru_cache==0.1.6
This 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.
//Oracle Identity Cloud Service connection parameters as a json var { "ClientId" : "clientid", "ClientSecret" : "clientsecret", "BaseUrl" : "https://idcs-1234.identity.oraclecloud.com", "AudienceServiceUrl" : "https://idcs-1234.identity.oraclecloud.com", "TokenIssuer" : "https://identity.oraclecloud.com", "scope" : "urn:opc:idm:t.user.me openid", "redirectURL": "http://localhost:8000/callback", "logoutSufix":"/oauth2/v1/userlogout" }
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 .
|
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() #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. The access token is stored as a cookie, which is then sent to the browser 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() #User Manager loaded with the configurations. um = IdcsClient.UserManager(getOptions()) #Using the access_token value to get an object instance representing the User Profile. u = um.getAuthenticatedUser(access_token) #Getting the user details in json object format. displayname = u.getDisplayName() #The application then adds these information to the User Session. request.session['access_token'] = access_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 access token, calls the getAuthenticatedUser
function to retrieve the user's information 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, then loads the User Manager with the configurations. am = IdcsClient.UserManager(getOptions()) #Using the access_token value to get an object instance representing the User Profile. u = am.getAuthenticatedUser(access_token) #Getting the user details in json format. jsonProfile = json.dumps(u.getUser()) #Getting User information to send to the My Profile page. displayname = request.session.get('displayname', 'displayname') #Rendering the content of the My Profile Page. return render(request, 'sampleapp/myProfile.html', {'displayname': displayname, 'jsonProfile':jsonProfile})
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 invalidates the user session 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): options = getOptions() url = options["BaseUrl"] url += options["logoutSufix"] del request.session['access_token'] del request.session['displayname'] return HttpResponseRedirect(url)