Created
May 9, 2024 19:31
-
-
Save therealcmj/04d1a9f1c7ed2fabf021f347d772e411 to your computer and use it in GitHub Desktop.
An example python script to use Device Code grant type with OCI IAM identity domains
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # these are all you need to change: | |
| idcs_url = 'https://idcs-XXX.identity.oraclecloud.com' | |
| oauth_clientID = 'YYY' | |
| oauth_clientSecret = 'ZZZ' | |
| # the rest of these variables can be left alone for now | |
| user_agent = 'devicetest.py' | |
| printRequests=True | |
| printResponses=True | |
| printResponsesPretty=True | |
| sleepFor=1 | |
| # import urllib2 | |
| import urllib | |
| import urllib.error | |
| import urllib.request | |
| import json | |
| import time | |
| def makeIDCSRequest( uri, postdata, ignore400=False ): | |
| req = urllib.request.Request( idcs_url + uri) | |
| req.add_header('User-Agent', user_agent) | |
| req.add_header('Accept', "application/json") | |
| if printRequests: | |
| print("URL: %s" % req.get_full_url()) | |
| print ("Request payload:") | |
| print (json.dumps( postdata, | |
| sort_keys=True, | |
| indent=4, | |
| separators=(',', ': ') | |
| )) | |
| try: | |
| response = urllib.request.urlopen(req, data=urllib.parse.urlencode(postdata).encode('ascii')) | |
| responseData = response.read() | |
| responseDataDict = json.loads( responseData ) | |
| except urllib.error.HTTPError as e: | |
| if ignore400 and ( e.code == 400): | |
| responseData = e.read() | |
| responseDataDict = json.loads( responseData ) | |
| else: | |
| print ("Exception caught") | |
| print ("Error code: %s" % e.code) | |
| print ("Reason : %s" % e.reason) | |
| print (e.read()) | |
| # raise the error again so we bomb out | |
| raise e | |
| if printResponses: | |
| if printResponsesPretty: | |
| print ("Response payload:") | |
| print (json.dumps( responseDataDict, | |
| sort_keys=True, | |
| indent=4, | |
| separators=(',', ': ') | |
| ) | |
| ) | |
| else: | |
| print (responseData) | |
| return responseDataDict | |
| postdata = { | |
| "response_type": "device_code", | |
| "scope": "openid offline_access", | |
| "client_id": oauth_clientID | |
| } | |
| print ("Making initial OAuth call to acquire device code...") | |
| responseDataDict = makeIDCSRequest( '/oauth2/v1/device', postdata ); | |
| # it's always good practice to check that you got back what you expected | |
| if ( "device_code" not in responseDataDict ) or \ | |
| ( "expires_in" not in responseDataDict ) or \ | |
| ( "user_code" not in responseDataDict ) or \ | |
| ( "verification_uri" not in responseDataDict ): | |
| # it's generally bad form to raise an Exception as a plain old Exception | |
| # but this is a (dumb) example app so I'm going to pretend it's OK | |
| raise Exception("Missing data in response from IDCS") | |
| # save the device code away in a local variable | |
| device_code = responseDataDict["device_code"] | |
| # tell the user to go to that URL | |
| print ("") | |
| print ("Open a browser, go to:") | |
| print (responseDataDict["verification_uri"]) | |
| print ("and enter the code " + responseDataDict["user_code"]) | |
| # then poll | |
| waiting = True | |
| postdata = { | |
| "grant_type": "urn:ietf:params:oauth:grant-type:device_code", | |
| "client_id": oauth_clientID, | |
| "device_code": device_code, | |
| "client_secret" : oauth_clientSecret | |
| } | |
| # print json.dumps( postdata ); | |
| while waiting: | |
| time.sleep(sleepFor) | |
| responseDataDict = makeIDCSRequest( '/oauth2/v1/token', postdata, True ); | |
| if "error" in responseDataDict and \ | |
| responseDataDict["error"] == "authorization_pending": | |
| print ("Waiting") | |
| elif "access_token" in responseDataDict: | |
| waiting = False | |
| access_token = responseDataDict["access_token"] | |
| print ("Acquired Access Token:") | |
| print (access_token) | |
| else: | |
| print ("Unexpected return data:") | |
| print (json.dumps( responseDataDict, | |
| sort_keys=True, | |
| indent=4, | |
| separators=(',', ': ') | |
| ) | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment