Enabling Client Registrations¶
Client Registrations¶
In certain cases, such as when Download Tracking is enabled, the OData service needs to track registered clients.
For this purpose, the CSDL must contain a ClientRegistration entity type and corresponding ClientRegistrationSet entity set.
The ClientRegistration entity type:
-
Must include a
ClientIDkey property of typeEdm.Int64 -
Must include a
ClientGUIDproperty of typeEdm.Guid -
May include an
AuthorizedUserproperty of typeEdm.String. If specified, this property will be populated automatically with the registration's authorized user name if the OData service is deployed with authentication enabled. Otherwise this property will benull. -
May include arbitrary other properties of use to the client application.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docs.oasis-open.org/odata/ns/edmx http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edmx.xsd http://docs.oasis-open.org/odata/ns/edm http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edm.xsd">
...
<edmx:DataServices>
<Schema Namespace="my.schema" Alias="Self" xmlns="http://docs.oasis-open.org/odata/ns/edm">
...
<EntityType Name="ClientRegistration">
<Key>
<PropertyRef Name="ClientID"/>
</Key>
<Property Name="ClientID" Type="Edm.Int64" Nullable="false"/>
<Property Name="ClientGUID" Type="Edm.Guid" Nullable="false"/>
<Property Name="AuthorizedUser" Type="Edm.String" Nullable="true" MaxLength="200"/>
</EntityType>
<EntityContainer Name="MyService">
...
<EntitySet Name="ClientRegistrationSet" EntityType="Self.ClientRegistration"/>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Client Credentials¶
Properties such as passwords, or other security credentials apart from AuthorizedUser, should not be stored in the
ClientRegistration entity type. Instead, the CSDL can contain a ClientCredentials entity type and corresponding
ClientCredentialsSet entity set.
Note
The Client Credentials feature feature is primarily intended to support secure integration with legacy back-end systems that do not support Token Exchange with SAP Business Technology Platform destinations. Otherwise use of this feature is discouraged.
Example:
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://docs.oasis-open.org/odata/ns/edmx http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edmx.xsd http://docs.oasis-open.org/odata/ns/edm http://docs.oasis-open.org/odata/odata/v4.0/os/schemas/edm.xsd">
...
<edmx:DataServices>
<Schema Namespace="my.schema" Alias="Self" xmlns="http://docs.oasis-open.org/odata/ns/edm">
...
<EntityType Name="ClientCredentials">
<Key>
<PropertyRef Name="ClientID"/>
</Key>
<Property Name="ClientID" Type="Edm.Int64" Nullable="false"/>
<Property Name="BackendUsername" Type="Edm.String" Nullable="true" MaxLength="200"/>
<Property Name="BackendPassword" Type="Edm.String" Nullable="true" MaxLength="200"/>
</EntityType>
<EntityContainer Name="MyService">
...
<EntitySet Name="ClientCredentialsSet" EntityType="Self.ClientCredentials"/>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Client credentials should be stored in secure client-side storage, preferably encrypted by an application passcode or
similar mechanism. Any attempt to upload client credentials to the server, by POSTing to the ClientCredentialsSet
entity set for example, will be rejected with response status code 405 (Method Not Allowed).
To enable the server to access the client credentials when needed, without having to persist them in the server's
database, every request from a client application to an OData service with a ClientCredentials entity type should be
accompanied by an X-Client-Credentials HTTP request header, where the header value contains the credentials entity
encoded as a JSON object within a data URI, using media type
application/json and Base64-encoded data. To facilitate this encoding of credentials, see ToJSON.dataURI and
HttpHeaders.withData in the client SDK documentation, or refer to the following example showing the encoding steps.
Example encoding of credentials entity with Username of secretuser and Password of secretpass:
- JSON-encoded entity:
{"Username":"secretuser","Password":"secretpass"} - Base64-encoded JSON:
eyJVc2VybmFtZSI6InNlY3JldHVzZXIiLCJQYXNzd29yZCI6InNlY3JldHBhc3MifQ== - Encoded as data URI:
data:application/json;base64,eyJVc2VybmFtZSI6InNlY3JldHVzZXIiLCJQYXNzd29yZCI6InNlY3JldHBhc3MifQ== - HTTP header:
X-Client-Credentials: data:application/json;base64,eyJVc2VybmFtZSI6InNlY3JldHVzZXIiLCJQYXNzd29yZCI6InNlY3JldHBhc3MifQ==
When you use the SAP BTP SDK for Android or iOS to build a client application, specify the values for headers
such as X-Client-Credentials in the customHeaders property of the OfflineODataParameters object, which is passed
to the constructor/initializer of OfflineODataProvider.
The Android com.sap.cloud.mobile.foundation.securestore.SecureKeyValueStore
and iOS Keychain Services
APIs are recommended for storing client credentials across application restarts.
Registration Header¶
Every client request from a client application to an OData service with client registrations must be accompanied by a
Client-Instance-ID HTTP request header, which uniquely identifies a particular instance of the client application on a
particular client computer. The header value should be in 36-character
UUID format, preferably a
Version 4 (random) variant.
When a client uses HTTP POST to the ClientRegistrationSet entity set to create a registration with the server, the
Client-Instance-ID header value is copied into the ClientGUID property of the newly created
ClientRegistration entity, and a corresponding ClientID property is automatically generated
by the server. The ClientID can be considered a short form of the ClientGUID, and is used by the server to associate
any client-specific information with the registration, such as download tracking data or client
identifiers for filter entities.
When you build client applications using the SAP BTP SDK for Android or iOS, you can specify values for
headers such as Client-Instance-ID in the customHeaders property of the OfflineODataParameters object that is
passed to the constructor/initializer of OfflineODataProvider. The client application should use the same
Client-Instance-ID value across application restarts (unless the client database is recreated, in which case a new
Client-Instance-ID should be used).
An application-specific local file can be used for storing Client-Instance-ID values across application restarts.
Recent versions of the client SDKs have an autoRegisterClient property in the OfflineODataParameters class, which can simplify the process of obtaining and storing the necessary client registration.
Registration Expiry¶
Inactive client registrations are automatically deleted after 49 days (by default). The expiry interval for inactive
registrations is one day less than the retainDeletionsFor property of the SQLDatabaseProvider class in the Server
OData API. You can modify this property by editing the generated ProviderSettings class and rebuilding/redeploying the
generated service.
The rationale for deferred expiration is as follows. Whenever data is to be deleted from the database, it is marked as logically deleted rather than being immediately physically deleted from the database. This allows for a client to be offline for an extended period, then come back online and execute delta queries to discover deletions (and other changes) that occurred while the client was offline. If the client was permitted to remain offline for longer than the deletion retention period, then, when the client comes online again to execute delta queries, it might fail to be notified of some deletions that occurred while it was offline. By forcing an inactive client's registration to expire one day before the deletion retention period, it can be ensured that the client will always be able either to successfully download all changes (including deletions) that occurred while the client was offline, or to be notified that the client's registration has expired.