PythonアプリケーションとOracle Identity Cloud Serviceの認証について

Python WebアプリケーションとOracle Identity Cloud Service間の認証について理解する準備ができています。内容は次のとおりです。

  • SDKをPythonアプリケーションとともに使用してOracle Identity Cloud Serviceで認証する場合に使用します。

  • Oracle Identity Cloud ServiceでPython SDKに対してサポートされている3レッグ認証フロー

  • Python SDKのメソッドおよび関数

3方向認証フローについて

Oracle Identity Cloud Serviceでは、Python SDKに対して3 - legged認証フローをサポートしています。このフローでは、ユーザーはOracle Identity Cloud Serviceと直接対話します。ユーザーのサイン・イン後、Oracle Identity Cloud Serviceは、SDKがユーザー・アクセス・トークンと交換する認可コードを発行します。このアクセス・トークンはPythonアプリケーションで使用して、アプリケーション内の保護されているリソースへのアクセス権をユーザーに付与できます。3つのレグ化フローでは、認可コード付与タイプを使用します。

セキュリティを強化するために、Oracleは、Python WebアプリケーションをOracle Identity Cloud Serviceと認証用に統合する3レッグ・フローを使用することをお薦めします。認可コード権限タイプを使用することで、再認証を行わずにOracle Identity Cloud Serviceによって保護されている他のアプリケーションにアクセスすることもできます。

SDKをPythonアプリケーションとともに使用するためのプライマリ・ユースケースについて

Python Webアプリケーションは、認証ユーザー用とログイン中のユーザーに関する詳細情報にアクセス用の2つのユースケースを実装しています。

次のデータ・フロー・ダイアグラムは、各ユースケースのWebブラウザ、WebアプリケーションおよびOracle Identity Cloud Service間のイベント、コールおよびレスポンスのフローを示しています。

図-ユースケース1:ユーザー認証

図の説明が続きます
「図-ユースケース1:ユーザー認証」の説明

データ・フローの動作は次のとおりです。

  1. ユーザーが保護されたリソースをリクエストします。

  2. 認証モジュールでは、SDKを使用して、Oracle Identity Cloud Serviceのリクエスト認証コードURLを生成し、このURLをWebブラウザへのリダイレクト・レスポンスとして送信します。

  3. WebブラウザはURLを呼び出します。

  4. Oracle Identity Cloud Service Sign Inページが表示されます。

  5. ユーザーは、Oracle Identity Cloud Serviceサインイン資格証明を送信します。

  6. ユーザーが正常にログインすると、Oracle Identity Cloud Serviceはユーザーのセッションを作成し、認可コードを発行します。

  7. Webアプリケーションは、バックエンド(またはサーバー間)コールを行い、ユーザー・アクセス・トークンの認可コードを交換します。

  8. Oracle Identity Cloud Serviceではアクセス・トークンが発行されます。

  9. セッションが確立され、ユーザーがホーム・ページにリダイレクトされます。

  10. Webアプリケーションのホーム・ページが表示されます。

図-ユースケース2:ユーザー詳細の取得

図の説明が続きます
「図-ユースケース2:ユーザー詳細の取得」の説明

データ・フローの動作は次のとおりです。

  1. ユーザーが/myProfileリソースをリクエストします。

  2. Webアプリケーションは、SDKを使用してOracle Identity Cloud Serviceを呼び出します。SDKは、ユーザー・セッションに格納されているアクセス・トークンをパラメータとして使用します。

  3. ユーザーの詳細がJSONオブジェクトとしてWebアプリケーションに送信されます。

  4. 「プロファイル」ページでは、JSONオブジェクトがHTMLコンテンツとしてレンダリングされます。

Python SDKのメソッドおよび関数について

Python SDKは、Webアプリケーションに含める必要がある、IdcsClient.pyおよびConstants.pyの2つのpythonファイルとして入手できます。これらのpythonファイルは、アプリケーションにも含める必要のあるサードパーティ・ライブラリに依存しています。これを含めるには、次のpip installコマンドを実行します。

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

このサンプルWebアプリケーションは、機能の形式でURLルートを実装するPython DJangoフレームワークを使用して開発されました。

Python SDKには、Oracle Identity Cloud Service接続情報にロードされたJSON変数が必要です。Python Webアプリケーションでは、次の情報を提供しているconfig.jsonファイルを使用します。

//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"
}

このSDKに必要な各属性の簡単な説明を次に示します。

表- Python SDKの必須属性

属性名 属性の説明
ClientId Oracle Identity Cloud Serviceコンソールを使用してWebアプリケーションを登録した後に生成されるクライアントIDの値。
ClientSecret Oracle Identity Cloud Serviceコンソールを使用してWebアプリケーションを登録した後に生成されるクライアント・シークレットの値。
BaseUrl Oracle Identity Cloud ServiceインスタンスのドメインURL。
AdminServiceUrl Oracle Identity Cloud Serviceインスタンスのドメイン名URL。これは通常、BaseUrlと同じです。
TokenIssuer ここに表示された値をそのまま使用します。
scope スコープにより、ユーザーにかわってアプリケーションがアクセスまたは処理できるデータが制御されます。アプリケーションではSDKが認証に使用されるため、有効範囲はopenidです。また、get user detailsユースケースも実装しており、そのためにもスコープurn:opc:idm:t.user.meを使用する必要があります。

logoutSufix属性とredirectURL属性は、どちらもアプリケーションによって使用されます。このため、SDKにとって必須ではありません。

アプリケーションによって、/auth URLをマップするauth関数定義が実装されます。Oracle Identity Cloud Serviceを使用してユーザーが認証すると、ブラウザがこのURLをリクエストします。

auth関数は、認証マネージャを初期化し、JSON構成属性をパラメータとして使用し、SDKを使用してOracle Identity Cloud Service認可コードURLを生成し、ブラウザをこの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)

次のパラメータを使用して、認可コードURLを生成します。

表-承認コードURLの生成に使用されるパラメータ

パラメータ名 パラメータ摘要
options["redirectURL"] サインインに成功すると、Oracle Identity Cloud ServiceによってユーザーのWebブラウザがこのURLにリダイレクトされます。このURLは、Oracle Identity Cloud Serviceコンソールで信頼できるアプリケーション用に構成するURLと一致している必要があります。
options["scope"] 認証のOAuthまたはOpenID Connectスコープ。このアプリケーションに必要なのはopenid認証のみです。
state Webアプリケーションは、このコードを使用して、Oracle Identity Cloud Serviceへの通信を確立できるかどうかをチェックします。パラメータは、OAuthプロトコルによって定義されます。
response_type 認可コード権限タイプで必要とされる値(例: code)。

callback関数は、認可コードのURLパラメータを使用して、アクセス・トークンをリクエストします。アクセス・トークンはCookieとして保存され、後で使用するためにブラウザに送信されます。

# 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})

myProfile関数は、ユーザーのアクセス・トークンにアクセスし、getAuthenticatedUser関数をコールしてユーザーの情報をJSONテキストとして取得し、その情報をmyProfile.htmlに送信してレンダリングします。

# 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})

アプリケーションとOracle Identity Cloud Serviceの間のシングルサインオンからユーザーにサイン・アウトするには、Python Webアプリケーションがlogout関数を実装している必要があります。このファンクションは、ユーザー・セッションを無効にした後、ユーザーをOracle Identity Cloud ServiceのOAuthログアウトURLにリダイレクトします。このURLは、config.jsonファイルでlogoutSufixパラメータとして設定されます。

# 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)