<jupyter_start><jupyter_text>OAuth2 e OpenID<jupyter_code>import requests
import os

os.environ['GCLOUD_PROJECT_ID']<jupyter_output><empty_output><jupyter_text>OAuth2.0OAuth2 e' un protocollo utilizzato per garantire ad un client l'autorizzazione per le API di un server.L'autorizzazione e' espressa attraverso un token, chiamato `access_token`, che deve essere contenuto negli header delle richieste API.  0. Registrazione dell'applicazione<jupyter_code>print('id:',     os.environ['GCLOUD_CLIENT_ID'])
print('secret:', 'GCLOUD_CLIENT_SECRET' in os.environ)<jupyter_output>id: 359913789820-tfbqpn1mpan21vgjb408i42rd1ruc9mv.apps.googleusercontent.com
secret: True<jupyter_text>A-1. Richiesta del tokenredirect 301 alla pagina di aturotizzazione, specificando `client_id` e `redirect_uri` dell'applicazione registrata<jupyter_code>from urllib.parse import quote
port = 8000

authorization_url = 'https://accounts.google.com/o/oauth2/v2/auth'
response_type     = 'code'
client_id         = os.environ['GCLOUD_CLIENT_ID']
redirect_uri      = quote(f'http://localhost:{port}')
scope             = quote('email openid https://www.googleapis.com/auth/drive.file')
state             = 'piccirimello'

params = '&'.join([
    f'response_type={response_type}', # Comportamento del server di autorizzazione
    f'client_id={client_id}',         # Identificativo dell'applicazione
    f'redirect_uri={redirect_uri}',   # Dove far redirect una volta che il processo di autorizzazione e' terminato
    f'scope={scope}',                 # Autorizzazioni richieste
    f'state={state}',                 # Stato che viene ritornato indietro al server
])
redirect_to = f'{authorization_url}?{params}'

print(redirect_to)<jupyter_output>https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=359913789820-tfbqpn1mpan21vgjb408i42rd1ruc9mv.apps.googleusercontent.com&redirect_uri=http%3A//localhost%3A8000&scope=email%20openid%20https%3A//www.googleapis.com/auth/drive.file&state=piccirimello<jupyter_text>A-2. Attesa dell'access tokenCi si mette in ascolto sulla porta specificata nel redirect, in attesa che il client compia il login.<jupyter_code>import http.server
from urllib.parse import urlparse

handler = http.server.SimpleHTTPRequestHandler

print('Waiting for authorization...')

with http.server.HTTPServer(('', port), handler) as server:
    sock, _ = server.get_request()
    raw_http = sock.recv(2048).decode('utf-8')
    
raw_url, _ = raw_http.split('\r\n', 1)
request_url = urlparse(raw_url)
print(raw_url)<jupyter_output>Waiting for authorization...
GET /?state=piccirimello&code=4%2F0AY0e-g7JqWPDR83xkLMaGZgtQlZF7zWO0BX-leo63FDcgPQ6HP7deDSEZ-xuZQfUFvvULQ&scope=email+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&prompt=none HTTP/1.1<jupyter_text>B-1. Lettura dell'access code ricevuto<jupyter_code>from urllib.parse import parse_qs
from pprint import  pprint

querystring = request_url.query
params = parse_qs(querystring)

pprint(params)
auth_code = params['code'][0]<jupyter_output>{'authuser': ['0'],
 'code': ['4/0AY0e-g5OTppuhm_1O5CGHBaXi2UVQL_N0yR5nuworeQKf6hQYfjuhVvpTokC1uDTzDG0xg'],
 'prompt': ['consent HTTP/1.1'],
 'scope': ['email https://www.googleapis.com/auth/userinfo.email openid '
           'https://www.googleapis.com/auth/drive.file'],
 'state': ['piccirimello']}<jupyter_text>B-2. Scambio autorization_code e credenziali client per access token<jupyter_code>import requests

response = requests.post('https://oauth2.googleapis.com/token', json={
    'code':          auth_code,
    'client_id':     os.environ['GCLOUD_CLIENT_ID'],
    'client_secret': os.environ['GCLOUD_CLIENT_SECRET'],
    'redirect_uri':  f'http://localhost:{port}',
    'grant_type':    'authorization_code'
})
jresponse = response.json()

access_token = jresponse['access_token']
pprint(jresponse)<jupyter_output>{'access_token': '<KEY>',
 'expires_in': 3599,
 'id_token': '<KEY>[...]<jupyter_text>C. Richiesta a Google Drive con access-token<jupyter_code>import hashlib, datetime

now = datetime.datetime.now().isoformat()
now_hash = hashlib.sha256(now.encode('utf-8')).hexdigest()

file_content = f'''
Data: {now}
Hash: {now_hash}
'''

print(file_content)
headers = {'Content-Type': 'text/plain', 'Authorization': f'Bearer {access_token}'}

drive_response = requests.post('https://www.googleapis.com/upload/drive/v3/files?uploadType=media',
                               headers=headers,
                               data=file_content)

jdrive_response = drive_response.json()
pprint(jdrive_response)
print(f'https://drive.google.com/open?id={jdrive_response["id"]}')<jupyter_output>https://drive.google.com/open?id=1nXhtwBQdtiwSesAXasInxtlA-CbvK9tw<jupyter_text>![authorization-code.png](attachment:authorization-code.png)  Autenticazione con OpenID<jupyter_code>import base64, json
jwt = jresponse['id_token']

head, body, checksum = jwt.split('.')

decoded_head = json.loads(base64.b64decode(head + '=='))
decoded_body = json.loads(base64.b64decode(body + '=='))
pprint(decoded_head)
pprint(decoded_body)<jupyter_output>{'at_hash': 'Oic0ve1kWdyb2UYmTBG4oA',
 'aud': '359913789820-tfbqpn1mpan21vgjb408i42rd1ruc9mv.apps.googleusercontent.com',
 'azp': '359913789820-tfbqpn1mpan21vgjb408i42rd1ruc9mv.apps.googleusercontent.com',
 'email': '<EMAIL>',
 'email_verified': True,
 'exp': 1619424551,
 'iat': 1619420951,
 'iss': 'https://accounts.google.com',
 'sub': '102559048848623069948'}
{'fraction_non_alphanumeric': 0.13580021873860737, 'fraction_numerical': 0.04265402843601896, 'mean_word_length': 5.928030303030303, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 29, 'https://': 10, 'lorem ipsum': 0, 'www.': 7, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '26562', 'license': 'MIT', 'n_tokens_mistral': 2172, 'n_tokens_neox': 2075, 'n_words': 302, 'path': 'notebook/OAuth2-presentation.ipynb', 'repo_name': 'ale-cci/Tesi-OAuth2', 'size': '6431'}