Skip to content

Instantly share code, notes, and snippets.

@brianv0
Last active March 28, 2019 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianv0/34ecaac33ee5892caeb46d29364c7d14 to your computer and use it in GitHub Desktop.
Save brianv0/34ecaac33ee5892caeb46d29364c7d14 to your computer and use it in GitHub Desktop.
IVOA Credential Store Example
credentials:
# Basic (Digest? depends on WWW-Authenticate working)
# securityMethod = ivo://ivoa.net/sso#BasicAA
https://username1@basic-ivoa.example.com:
username: ...
password: bar
# Basic At subpath
https://username1@basic-ivoa.example.com/subpath/resource:
username: ...
password: qux
# OAuth2 - Simple config - e.g. `Authorization: Bearer [access_token]`
# securityMethod = ivo://ivoa.net/sso#OAuth
https://username2@oauth-ivoa.example.com:
access_token: ...
# OAuth2 - PKCE + Refresh - assumes the client was configured in some way
# securityMethod = ivo://ivoa.net/sso#OAuth
https://username3@oauth-ivoa.example.com:
# The application itself will have a default client_id + redirect uri
# that providers could trust. Otherwise, this could be an override.
client_id: 1234567890
redirect_uri: com.example.ivoa
token_endpoint: https://ivoa.example.com/oauth/token
refresh_token: ...
access_token: ...
# refresh_token and access_token could be managed by a daemon
id_token: ...
# Which token to use for accessing. id_token is often a JWT
use: access_token # [access_token (default) || id_token]
# Use token with x-oauth-basic instead of with `Authorization: Bearer [token]`
x-oauth-basic: true # [false (default) || true]
# TLS Client
https://username4@tls-ivoa.example.com:
# base64 encoded
client_certificate: "..."
# Extra certificate chain information?
import json
import keyring
import yaml
from urllib.parse import urlparse
SERVICE_NAME = "IVOA Credential Helper"
def load_keyring(file):
config = yaml.load(file, Loader=yaml.SafeLoader)
for cred, cred_object in config["credentials"].items():
parsed_cred = urlparse(cred)
if parsed_cred.path == "/":
print("WARNING: Omitting trailing slash from credential")
cred = cred[:-1]
cred_json = json.dumps(cred_object)
keyring.set_password(SERVICE_NAME, cred, cred_json)
class CredentialHelper:
def __init__(self, hostname_to_user):
self.hostname_to_user = hostname_to_user
def get_credential(self, url):
parsed = urlparse(url)
insecure = parsed.scheme != "https"
scheme = parsed.scheme
hostname = parsed.hostname
port = f":{parsed.port}" if parsed.port else ""
path = parsed.path
cred_base_url = f"{scheme}://{hostname}{port}"
cred_full_url = f"{cred_base_url}{path}"
if cred_full_url in self.hostname_to_user:
# Check for exact match
username = self.hostname_to_user[cred_full_url]
username = f"{username}@" if username else ""
cred_lookup_url = f"{scheme}://{username}{hostname}{port}{path}"
elif cred_base_url in self.hostname_to_user:
# Fallback to base URL with a username
username = self.hostname_to_user[cred_base_url]
username = f"{username}@" if username else ""
cred_lookup_url = f"{scheme}://{username}{hostname}{port}"
else:
# Fallback to base URL with no username
cred_lookup_url = cred_base_url
credential = keyring.get_credential(SERVICE_NAME, cred_lookup_url)
if credential:
return json.loads(credential.password)
return None
# Example
load_keyring(open("credentials.yaml"))
auth_context = {
"https://basic-ivoa.example.com": "username1",
"https://basic-ivoa.example.com/subpath/resource": "username1"
}
helper = CredentialHelper(auth_context)
helper.get_credential("https://basic-ivoa.example.com")
helper.get_credential("https://basic-ivoa.example.com/foo/bar")
helper.get_credential("https://basic-ivoa.example.com/subpath/resource")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment