Table of Contents
This concept defines a smart contract which allows the owner of a resource to grant access to resources he owns to particular users. This Work ist part of a discontinued collaboration within IDUnion project
In general, there are two types of accounts: externally owned accounts, controlled by private keys, and contract accounts, controlled by their contract code. See Ethereum Accounts.
A resource is available via the internet and can be localized and access by an Uniform Resource Locator (URL).
The ProtectionAuthorizationId is the 20 byte address of an EOA controlled by the provider. The owner authorizes the controller of this Id to use a smart contract to protect his resources.
The UserId uniquely identifies the user. It is the 20 byte address of an EOA controlled by the user.
The owner is a special user which owns resources. The ownership of resources is defined by the content of resources. The resources owned by the owner contain the UserId of the owner.
Smart contracts digitize agreements by turning the terms of an agreement into computer code that automatically executes when the contract terms are met. They are stored on a blockchain, addressed by a contract account, behave exactly as programmed and cannot be changed. See Smart Contracts.
The ContractId is the 20 byte address of a contract account. See Ethereum Accounts.
Resources are protected by a default deny policy. In order to enable the resource owner to define access policies the resource needs to be registered at the smart contract by the resource provider. Beforehand, the resource provider needs the entitlement of the resource owner to protect the resource on his behalf.
@startuml title Protect Resource participant "Resource Provider" as PROVIDER participant "SCUMA" as SC participant "Owner" as OWNER activate PROVIDER PROVIDER <-- OWNER : GET ResourceURL PROVIDER --> OWNER : 401 WWW-authenticate: Challenge PROVIDER <-- OWNER : GET ResourceURL Authorization: Credential PROVIDER -> PROVIDER: Verifies Credential PROVIDER --> OWNER : 200 Resource Set-Cookie: SessionCookie deactivate PROVIDER PROVIDER <-- OWNER : POST ProtectResource(ResourceURL) Cookie: SessionCookie activate PROVIDER opt Protection Authorization not yet available PROVIDER -> PROVIDER : Generate ProtectionAuthorizationId PROVIDER --> OWNER : 302 RequestProtectionAuthorization(ProtectionAuthorizationId) activate OWNER SC <- OWNER : RegisterProvider(ProtectionAuthorizationId) : Boolean PROVIDER <-- OWNER : POST ContractId deactivate OWNER PROVIDER -> PROVIDER : Store Mapping Owner -> ContractId, ProtectionAuthorizationId end PROVIDER -> PROVIDER : Generate ProtectedResourceId PROVIDER --> SC : RegisterResource(ProtectionAuthorizationId, ProtectedResourceId) activate SC SC->SC : CheckProtectionAuthorization : Boolean SC->SC : RegisterId : Boolean PROVIDER <-- SC : Success deactivate SC PROVIDER -> PROVIDER : Store Mapping ResourceURL -> ProtectedResourceId PROVIDER --> OWNER : 200 ProtectedResourceId deactivate PROVIDER SC <- OWNER : SetRule(ProtectedResourceId, UserID, Methods) : Boolean @enduml
The user access the resource via the interfaces provided by the resource provider using his EOA. The provider maps the resource request onto the protected resources and asks the smart contract for permissions. The smart contract returns the permissions which then are enforced by the provider.
@startuml title Access Resource participant "User" as USER participant "Resource Provider" as PROVIDER participant "SCUMA" as SC activate PROVIDER USER --> PROVIDER : GET ResourceURL USER <-- PROVIDER : 401 WWW-authenticate: Challenge USER --> PROVIDER : GET ResourceURL Authorization: Credential PROVIDER -> PROVIDER: Verifies Credential PROVIDER -> PROVIDER : Maps resource request onto ProtectedResourceIds activate SC PROVIDER --> SC : RequestsPermissions(\n listOf(PermissionRequest(protectedResourceID, requestedMethods)),\n userId\n) SC->SC : CheckProtectionAuthorization(ProtectionAuthorizationId) : Boolean SC->SC : CheckAccessRules(\n listOf(PermissionRequest(protectedResourceID, requestedMethods)),\n userId\n) : listOf(Permission(protectedResourceID, grantedMethods)) PROVIDER <-- SC : listOf(Permission(protectedResourceID, grantedMethods)) deactivate SC PROVIDER->PROVIDER : EnforcePermissions USER <-- PROVIDER : 200 Resources Coookie: SessionCookie @enduml
kether-plugin and kether needs to be installed to MavenLocal to build this project.
There are four API supported by the scuma library:
-
Management API between resource owner and resource provider
-
Access API between user and resource provider
-
Control API between resource owner and SCUMA
-
Protection API between resource provider and SCUMA
The Management API and the Access API should be implemented according to the API used to access the resoures. The scuma library only provides support functions for EOA based authentication. The actual implementations of the Management API and the Access API are out of scope of this specification.
The Control and Protection API uses the Ethereum JSON RPC protocol to interact with Ethereum clients and the smart contracts hosted on the Ethereum block chain. The scuma library hides the complexity of the Ethereum JSON RPC protocol and allows to interact with the scuma contract by an interface entirely defined in kotlin.
The User APIs are the interfaces between the users (resource owner and resource user) and the resource provider. They are mainly defined by the capabilities of the resource provider. In case of FHIR the resource server provides a REST interface HL7 - FHIR to provide access to medical resources. Further, the resource owner uses the Management API to request protection of accessed resources and to get information about protected resources (e.g. the protected resource id). In order to make sure that these interfaces are only used by the authorized users, the users need to be authenticated by the resource server.
HTTP Origin-Bound Authentication (HOBA) RFC7486 is a digital-signature-based design for an HTTP authentication method. HOBA is specified to use RSA signature but allows registration of other signature schemes. HOBA was extented to use SECP2561K1 signatures. This extension allows the user to authenticate against the server provides by using his external owned address and the corresponding private key.
-
The user connects to the resource server and makes a FHIR request:
GET /resource HTTP/1.1 HOST: resourceserver.com
-
The server rejects the request with status code 401 and includes a challenge in the WWW-Authenticate header:
HTTP/1.1 401 Unauthorized WWW-Authenticate: HOBA challenge="MPl_cQSW5Aa40kGGo6haUsm4Kkzs7pQ8t4are0mzD9s=" max-age=10 realm="scuma"
-
challenge
is a base64url-encoded challenge value that the server chose to send to the client. The challenge is chosen so that it is infeasible to guess and is derived from a random byte string of 32 bytes (256 bits). -
max-age
specifies the number of seconds from the time the HTTP response is emitted for which responses to this challenge can be accepted; for example, "max-age: 10" would indicate ten seconds. If max-age is set to zero, then that means that only one signature will be accepted for this challenge. -
realm
indicates the scope of protection in the manner described in RFC7235. Therealm
attribute MUST NOT appear more than once.
-
-
The user signs the challenge RFC7486-section2 and repeats the original request with an Authorization header containing the signed challenge RFC7486-section3 :
GET /resource HTTP/1.1 HOST: resourceserver.com Authorization: HOBA result="0xfe3b557e8fb62b89f4916b721be55ceb828db d73.eNIv3lOevIwjzuyrxGkliYnyAXUUuNC_oQZqplhO6rwp555smaglDfbHCroJdNG K9eqFgcVy4dL89nKC18hPk=.OncuAM2XAKi97RdjL7JgImdZ4a2FmCZSWgULpXF0q_B YAyALY35DlJGSiZjMb-2oDvvIcuh7teYJ4j2xXFikPAA="
-
result
is a dot-separated string that includes kid, challenge, nonce and signature:kid + '.' + challenge + '.' + nonce +'.' + sig
-
kid
key identifier. EOA of the resource owner -
challenge
challenge as received in the WWW-Authentication header -
nonce
a random value chosen by the resource owner derived from a random byte string of 32 byte length
-
-
-
The resource server verifies the credential received in the Authorization header by verifying the signature using the received parameters and additional context information RFC7486-section2. Further it checks that the response was received within the specified
max-age
. -
After successful authentication the server returns the requested resource. The response shall include a session cookie that allows the user client to indicate its authentication state in future requests - HTTP State Management Mechanism - RFC6265 .
The server uses the class ``HobaAuthenticationChallenge to create the Hoba challenge and sends the challenge in the WWW-Authententication header in a 401 response:
// challenge is 256bit random
val challenge = Random.nextBytes(32)
// realm defines the context
// max-age requests the client to answer within the next 10s
val hobaAuthenticationChallenge = HobaAuthenticationChallenge(
maxAge = 10,
realm = "scuma",
challenge = challenge
)
val wwwAuthenticationContent = hobaAuthenticationChallenge.toString()
The user client signs the challenge, repeats the original request with an authorization header which contains the signed challenge. The server receives the request and verifies the authorization header:
val hobaAuthorizationCedential = HobaAuthorizationCedential.fromString(authorizationHeaderContent)
// In order to verify the signature the server has to hand over its orgin as specified in its server certificate and the predefined realm used in the challenge.
assert(hobaAuthorizationCedential.verify(
origin = origin,
realm = "scuma"
)
)
The client receives the challenge from the server in the WWW-Authententication header of a 401 response and repeats the rejected request with an authorization header which contains the signed challenge as credential:
// nonce is 256bit random
val nonce = Random.nextBytes(32)
val hobaAuthorizationChallenge = HobaAuthenticationChallenge.fromString(wwwAuthenticationHeaderContent)
// In order to create the credential the client takes the challenge from the received hoba authentication challenge and an randomly choosen nonce.
val hobaAuthorizationCedential = hobaAuthorizationCedential(
challenge = hobaAuthorizationChallenge.challenge,
nonce = nonce
).apply{
// The client signs the challenge using his private key and the origin of the server taken from the server certificate.
sign(privateKey, origin)
}
val authorizationHeaderContent = hobaAuthorizationCedential.toString()
The scuma library has extended the HOBA RFC by a new signature algorithm. Instead of the defined RSA algorithms the scuma library uses SECP256K1. That is the crypto algorithm used by the Ethereum block chain. So the cryptographic keys bound to the EOAs of the users can be used for authentication.
In case high level of assurance is required it is recommended to use hardware backed keys (e.g. Android StrongBox). Ethereum uses SECP256K1 by default which unfortunately is not supported by secure elements (e.g. „Titan™ M“- secure chip). However, when running nodes in a private network, it is possible to configure an alternative elliptic curve. E.g. Hyperledger Besu allows to configure the elliptic curve in the network section of the genesis file (see Hyperledger Besu: Using alternative elliptic curves).
A detailed description of the protocol for the management of protected resources is out of scope of this specification. The actual implementation of the protocol messages should be choosen in a way that fits best to the access protocol of the managed resources. E.g. in case of FHIR a REST-API is defined to request and cancel protection and to get information about protected resources.
-
DID instead of EOA
-
attribute/group based access control (e.g. by using 1-of-N tree signatures)
-
privacy aware policies (e.g. by using zkay: A Language for Private Smart Contracts on Ethereum)
EUROPEAN UNION PUBLIC LICENCE v. 1.2
EUPL © the European Union 2007, 2016
Following terms apply:
-
Copyright notice: Each published work result is accompanied by an explicit statement of the license conditions for use. These are regularly typical conditions in connection with open source or free software. Programs described/provided/linked here are free software, unless otherwise stated.
-
Permission notice: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
The copyright notice (Item 1) and the permission notice (Item 2) shall be included in all copies or substantial portions of the Software.
-
The software is provided "as is" without warranty of any kind, either express or implied, including, but not limited to, the warranties of fitness for a particular purpose, merchantability, and/or non-infringement. The authors or copyright holders shall not be liable in any manner whatsoever for any damages or other claims arising from, out of or in connection with the software or the use or other dealings with the software, whether in an action of contract, tort, or otherwise.
-
The software is the result of research and development activities, therefore not necessarily quality assured and without the character of a liable product. For this reason, gematik does not provide any support or other user assistance (unless otherwise stated in individual cases and without justification of a legal obligation). Furthermore, there is no claim to further development and adaptation of the results to a more current state of the art.
-
-
Gematik may remove published results temporarily or permanently from the place of publication at any time without prior notice or justification.