External authorization¶
A Mesh server may be protected by an external authorization server, where the clients like Python SDK authenticate and request access tokens. Tokens obtained from the external authorization server are then sent in the Authorization header when making a call to the Mesh API.
This is required by the Mesh server if OAuth is enabled for the gRPC interface in the Mesh configuration file.
For security reasons authentication also requires TLS to be enabled, and you might therefore need Mesh’s TLS certificate in the below examples.
Token format¶
Mesh supports OAuth 2.0 JSON Web Token (JWT) access tokens. They need to meet the following requirements:
The access token signed using RSA algorithm.
Authorization is done using roles claim that must be part of the access token.
User’s claims: name and oid must be part of the access token.
Azure Active Directory (Azure AD) supports all OAuth 2.0 flows.
Example¶
from volue import mesh
# Most certificates won't work with IP addresses, therefore
# you'll need to be able to resolve the Mesh server by name,
# either through your DNS configuration, or through /etc/hosts.
with open("certificate.pem", "rb") as f:
certificate = f.read()
token = "my_access_token" # obtain it from authorization server
# mesh.domain.com is the address of the Mesh server.
connection = mesh.Connection.with_external_access_token(
"mesh.domain.com:50051", certificate, token
)
print(connection.get_user_identity())
For more complex example please refer to connect_using_external_access_token.py:
from datetime import datetime
import helpers
from volue.mesh import Connection
def main(address, tls_root_pem_cert):
"""
Showing how to authorize to gRPC Mesh server using externally obtained
access token, e.g: a OAuth JWT. Obtaining the access token is out of scope
for this example.
Depending on your environment, e.g.: Azure AD, using libraries like
Microsoft Authentication Library (MSAL) for getting the tokens is
suggested.
"""
token = "my_token"
connection = Connection.with_external_access_token(
address, tls_root_pem_cert, access_token=token
)
with connection.create_session() as session:
# Print user information contained in the access token.
user_identity = connection.get_user_identity()
print(user_identity)
# Read some time series data.
# This requires the user has time series read permissions.
timeseries_key = 1388
timeseries = session.read_timeseries_points(
timeseries_key, datetime(2014, 1, 1), datetime(2015, 1, 1)
)
print(timeseries.arrow_table.to_pandas())
# For long running sessions it may be necessary to refresh the access
# token.
# Other possibility would be to catch grpc.RpcError with status code
# UNAUTHENTICATED and then get new access token and update it in the
# Mesh connection using `update_external_access_token`.
connection.update_external_access_token("my_new_access_token")
if __name__ == "__main__":
# This requires Mesh server to be running with enabled TLS and OAuth options.
# Obtaining access token is out of the scope for this example.
address, tls_root_pem_cert = helpers.get_connection_info()
# main(address, tls_root_pem_cert)
Internals¶
Mesh validates access tokens that are sent with every call to the server. Validation means checking token’s:
RSA signature
integrity - to make sure no one tampered with it
expiration time
claims like audience, scope, etc.
Additionally it checks if user is permitted to access given API by checking the roles claim in the access token.
Access tokens have an expiration time, after which they’re no longer valid, and
a new access token is required. To provide new access token create either a new
connection or use volue.mesh.Connection.update_external_access_token()
.