Published

OGC Engineering Report

Testbed-18: Secure Asynchronous Catalog Engineering Report
Yves Coene Editor Christophe Noel Editor
OGC Engineering Report

Published

Document number:22-018
Document type:OGC Engineering Report
Document subtype:
Document stage:Published
Document language:English

License Agreement

Use of this document is subject to the license agreement at https://www.ogc.org/license


I.  Executive Summary

This OGC Testbed-18 Engineering Report (ER) describes the results of the Secure, Asynchronous Catalogs Task in the Testbed-18 Catalogs, Filtering, and Moving Features (CMF) thread. This task explored the following.

The Engineering Report assumes that the reader has some familiarity with OGC CSW, ISO19115 and the draft OGC API-Records Standards. It summarizes the options investigated and describes in detail the following main achievements.

A major result of the activity is the genericity of the proposed solutions. Both the Data Centric Security and the asynchronous communication via subscription models apply equally well to other API, including other OGC (JSON) API or other catalog API including OpenSearch or SpatioTemporal Asset Catalogs (STAC) or other JSON(-LD)-based metadata encodings including GeoDCAT-AP, “OGC EO Dataset Metadata GeoJSON(-LD) Encoding Standard” OGC 17-003r2, “EO Collection GeoJSON(-LD) Encoding” OGC 17-084r1, Service metadata as per OGC 19-020r1, STAC Collection Specification and STAC Item Specification.

During the activity, several areas requiring further work were identified, which are documented in a Future Work chapter of the Engineering Report. The proposed future work items include the following.

II.  Keywords

The following are keywords to be used by search engines and document catalogues.

OGC, API-Records, Catalog, CSW, DCS, ISO-19115, security, web service

III.  Security considerations

No security considerations have been made for this document.

IV.  Submitting Organizations

The following organizations submitted this Document to the Open Geospatial Consortium (OGC):

V.  Submitters

All questions regarding this submission should be directed to the editor or the submitters:

Name Affiliation Role
Yves Coene Spacebel s.a. Editor
Christophe Noël Spacebel s.a. Editor
Andreas Matheus Secure Dimensions GmbH Contributor
Eugene Yu George Mason University Contributor
Li Lin George Mason University Contributor
Philip Hawkins Helyx Contributor
Bart Cosyn agentschap Digitaal Vlaanderen Contributor
Loes Deventer agentschap Digitaal Vlaanderen Contributor
Geraldine Nolf agentschap Digitaal Vlaanderen Contributor

VI.  Abstract

This OGC Testbed-18 Engineering Report (ER) describes the results of the Secure, Asynchronous Catalogs Task in the Testbed-18 Catalogs, Filtering, and Moving Features (CMF) thread. This task explored the following.

Testbed-18: Secure Asynchronous Catalog Engineering Report

1.  Scope

This is the OGC Testbed-18 Engineering Report (ER) documenting the results of the Secure, Asynchronous Catalogs Task. It describes the following.

Secure, asynchronous catalogs are contributions to open science environments. Such catalogs help address challenges created by more and more data becoming available and the corresponding complexity of discovery and binding.

This Testbed-18 Engineering Report covers contributions in the following areas.

2.  Normative references

The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.

Open API Initiative: OpenAPI Specification 3.0.2, 2018 https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md

R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, T. Berners-Lee: IETF RFC 2616, Hypertext Transfer Protocol — HTTP/1.1. RFC Publisher (1999). https://www.rfc-editor.org/info/rfc2616.

A.B. Roach: IETF RFC 5989, A SIP Event Package for Subscribing to Changes to an HTTP Resource. RFC Publisher (2010). https://www.rfc-editor.org/info/rfc5989.

M. Nottingham: IETF RFC 8288, Web Linking. RFC Publisher (2017). https://www.rfc-editor.org/info/rfc8288.

J. Snell: IETF RFC 7240, Prefer Header for HTTP. RFC Publisher (2014). https://www.rfc-editor.org/info/rfc7240.

M. Jones, J. Bradley, N. Sakimura: IETF RFC 7515, JSON Web Signature (JWS). RFC Publisher (2015). https://www.rfc-editor.org/info/rfc7515.

M. Jones, J. Hildebrand: IETF RFC 7516, JSON Web Encryption (JWE). RFC Publisher (2015). https://www.rfc-editor.org/info/rfc7516.

M. Jones: IETF RFC 7517, JSON Web Key (JWK). RFC Publisher (2015). https://www.rfc-editor.org/info/rfc7517.

M. Jones, J. Bradley, N. Sakimura: IETF RFC 7519, JSON Web Token (JWT). RFC Publisher (2015). https://www.rfc-editor.org/info/rfc7519.

M. Jones: IETF RFC 7797, JSON Web Signature (JWS) Unencoded Payload Option. RFC Publisher (2016). https://www.rfc-editor.org/info/rfc7797.

M. Jones, J. Bradley, H. Tschofenig: IETF RFC 7800, Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs). RFC Publisher (2016). https://www.rfc-editor.org/info/rfc7800.

H. Butler, M. Daly, A. Doyle, S. Gillies, S. Hagen, T. Schaub: IETF RFC 7946, The GeoJSON Format. RFC Publisher (2016). https://www.rfc-editor.org/info/rfc7946.

A. Rundgren, B. Jordan, S. Erdtman: IETF RFC 8785, JSON Canonicalization Scheme (JCS). RFC Publisher (2020). https://www.rfc-editor.org/info/rfc8785.

Kellog G., Champin P., Longley D. : W3C JSON-LD 1.1, A JSON-based Serialization for Linked Data, W3C Recommendation 16 July 2020 https://www.w3.org/TR/json-ld11/

CEOS: CEOS-OPENSEARCH-BP-V1.3, CEOS OpenSearch Best Practice Document, Version 1.3 https://ceos.org/document_management/Working_Groups/WGISS/Documents/WGISS%20Best%20Practices/CEOS%20OpenSearch%20Best%20Practice.pdf

SEMIC: GeoDCAT-AP — Version 2.0.0, A geospatial extension for the DCAT application profile for data portals in Europe, Version 2.0 https://semiceu.github.io/GeoDCAT-AP/releases/2.0.0/

SEMIC: DCAT-AP — Version 2.1, DCAT Application Profile for data portals in Europe, Version 2.0 https://joinup.ec.europa.eu/collection/semantic-interoperability-community-semic/solution/dcat-application-profile-data-portals-europe/release/210

ISO: ISO19115:2003/Cor1:2006, Geographic Information – Metadata – Implementation specification http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=44361

ISO: ISO19115-1:2014, Geographic Information – Metadata – Part 1: Fundamentals https://www.iso.org/standard/53798.html

ISO: ISO19115-3, Geographic Information – Metadata – Part 3: XML schema implementation for fundamental concepts http://www.iso.org/iso/home/store/catalogue_ics/catalogue_detail_ics.htm?csnumber=32579

ISO: ISO 19139:2007, Geographic Information – Metadata XML, http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=32557

Uwe Voges, Kristian Senkler: OGC 07-045r2, OpenGIS® Catalogue Services Specification 2.0.2 — ISO Metadata Application Profile: Corrigendum. Open Geospatial Consortium (2022). https://portal.ogc.org/files/80534.

Richard Martell: OGC 07-110r4, CSW-ebRIM Registry Service — Part 1: ebRIM profile of CSW. Open Geospatial Consortium (2009). https://portal.ogc.org/files/?artifact id=31137.

Uwe Voges: OGC 08-197r4, INSPIRE Conformance Class of OGC Cataloguing of ISO Metadata (CIM) using the ebRIM profile of CS-W, 2011-10-11

Jerome Gasperi, Frédéric Houbie, Andrew Woolf, Steven Smolders: OGC 10-157r4, OGC® Earth Observation Metadata profile of Observations & Measurements. Open Geospatial Consortium (2016). https://docs.ogc.org/is/10-157r4/10-157r4.html.

Frédéric Houbie, Steven Smolders: OGC 11-035r1, EO Product Collection, Service and Sensor Discovery using the CS-W ebRIM Catalogue. Open Geospatial Consortium (2013). https://portal.ogc.org/files/?artifact id=53276.

Pedro Gonçalves, Uwe Voges: OGC 13-026r9, OGC OpenSearch Extension for Earth Observation, 2019 https://docs.opengeospatial.org/is/13-026r9/13-026r9.html

Uwe Voges, Frédéric Houbie, Nicolas Lesage, Marie-Lise Vautier: OGC 13-084r2, OGC I15 (ISO19115 Metadata) Extension Package of CS-W ebRIM Profile 1.0. Open Geospatial Consortium (2014). https://portal.ogc.org/files/?artifact id=56905.

Y. Coene, U. Voges, O. Barois: OGC 17-003r2, OGC EO Dataset Metadata GeoJSON(-LD) Encoding Standard. Open Geospatial Consortium (2020). https://docs.ogc.org/is/17-003r2/17-003r2.html.

Clemens Portele, Panagiotis (Peter) A. Vretanos, Charles Heazel: OGC 17-069r3, OGC API — Features — Part 1: Core. Open Geospatial Consortium (2019). https://docs.ogc.org/is/17-069r3/17-069r3.html.

Y. Coene, U. Voges, O. Barois: OGC 17-084r1, EO Collection GeoJSON(-LD) Encoding. Open Geospatial Consortium (2021). https://docs.ogc.org/bp/17-084r1/17-084r1.html.

Michael A. Leedahl: OGC 19-016r1, OGC Testbed-15: Data Centric Security. Open Geospatial Consortium (2019). https://docs.ogc.org/per/19-016r1.html.

Yves Coene: OGC 19-020r1, OGC Testbed-15: Catalogue and Discovery Engineering Report. Open Geospatial Consortium (2019). https://docs.ogc.org/per/19-020r1.html.

Panagiotis (Peter) A. Vretanos, Clemens Portele: OGC 19-079r1, OGC API — Features — Part 3: Filtering, https://docs.opengeospatial.org/DRAFTS/19-079r1.html

Panagiotis (Peter) A. Vretanos, Clemens Portele: OGC 20-002, OGC API — Features — Part 4: Create, Replace, Update and Delete, https://docs.ogc.org/DRAFTS/20-002.html

Panagiotis (Peter) A. Vretanos, Tom Kralidis, Charles Heazel: OGC 20-004, OGC API – Records – Part 1: Core, 2019 https://docs.ogc.org/DRAFTS/20-004.html

Aleksandar Balaban: OGC 20-021r2, OGC Testbed-16: Data Centric Security Engineering Report. Open Geospatial Consortium (2021). https://docs.ogc.org/per/20-021r2.html.

Charles Heazel: OGC 20-024, OGC API — Common — Part 2: Geospatial Data, 2022 https://docs.ogc.org/DRAFTS/20-024.html

Aleksandar Balaban, Andreas Matheus: OGC 21-020r1, OGC Testbed-17: Data Centric Security ER. Open Geospatial Consortium (2022). https://docs.ogc.org/per/21-020r1.html.

Panagiotis (Peter) A. Vretanos, Clemens Portele: OGC 21-065, Common Query Language (CQL2), https://docs.ogc.org/DRAFTS/21-065.html

Andreas Matheus: OGC 22-014, Testbed-18: Key Management Service API Engineering Report, http://ogc.pages.ogc.org/T18-Secure_Asynchronous_Catalogs/documents/D008/document.html

C. Lagoze, H. Van de Sompel et al.: OAI-PMH, Protocol Version 2.0, The Open Archives Initiative Protocol for Metadata Harvesting, 2015 https://www.openarchives.org/OAI/openarchivesprotocol.html

3.  Terms, Definitions, and Abbreviated Terms

3.1.  Terms and Definitions

3.1.1.  Access Token

A token that can be provided as part of a service request that grants access to the service being invoked on. This is part of the OpenID Connect and OAuth 2.0 specification [OGC 21-020r1].

3.1.2.  Data-Centric Security

Data-centric security emphasizes the dependability of the data itself rather than the security of networks, servers, or applications [Wikipedia].

3.1.3.  (Spatial) Data Set

Identifiable collection of (spatial) data [INSPIRE].

3.1.4.  (Spatial) Data Set Series

Collection of (spatial) data sets sharing the same product specification [INSPIRE].

3.1.5.  Discovery Service

Service that makes it possible to search for spatial data sets and services on the basis of the contents of the corresponding metadata and to display the contents of the metadata [INSPIRE].

3.1.6.  Granule

A granule is the finest granularity of data that can be independently managed. A granule usually matches the individual file of EO satellite data [CEOS-BP].

3.1.7.  STANAG

In NATO, Standardization Agreement defines processes, procedures, terms, and conditions for common military or technical procedures or equipment between the member countries of the alliance.

3.2.  Abbreviated terms

AP

Application Package

API

Application Programming Interface

CEOS

Committee on Earth Observation Satellites

CQL

Common Query Language

CSW

Catalogue Service for the Web

DCAT

Data Catalog Vocabulary

DCS

Data Centric Security

DEK

Data Encryption Key

DPoP

Demonstrating Proof-of-Possession

EO

Earth Observation

EP

Extension Package

ESA

European Space Agency

HTTP

Hypertext Transfer Protocol

IdP

Identity Provider

INSPIRE

INfrastructure for SPatial InfoRmation in Europe

ISO

International Organization for Standardization

JOSE

Javascript Object Signing and Encryption

JSON

JavaScript Object Notation

JWE

JSON Web Encryption

JWK

JSON Web Key

JWS

JSON Web Signature

JWS/CT

JSON Web Signature Clear Text

JWT

JSON Web Token

KEK

Key Encryption Key

KMS

Key Management System

OAI-PMH

Open Archive Initiative Protocol for Metadata Harvesting

OGC

Open Geospatial Consortium

REST

Representational State Transfer

STAC

SpatioTemporal Asset Catalog

STANAG

Standardization Agreement

SWG

Standard Working Group

TIE

Technology Integration Experiment

UML

Unified Modeling Language

URI

Uniform Resource Identifier

URL

Uniform Resource Locator

XML

eXtensible Markup Language

4.  OGC API-Records tailoring

4.1.  Introduction

This chapter includes the following.

  1. Whether OGC API – Records can support classical discovery workflows comparable with OGC CSW/ISO 19115 setups.

  2. A proposed tailoring based on the use cases and requirements gathered during the project.

4.1.1.  CSW ISO AP / ISO19115 Setups

OGC CSW has been used for ISO19115 metadata (and in particular its XML encoding ISO19139(-2)) extensively in the past. The CSW ISO Application Profile (AP) OGC 07-045r1 is widely implemented in Europe as the INSPIRE discovery service as one of the INSPIRE Network Services [3]. In addition, the INSPIRE community uses ISO19115 metadata and its XML encodings (e.g., ISO19139(-2)) for encoding dataset, dataset series, and services as explained in the Technical Guidance document [4]. The Joint Research Centre (JRC) of the European Commission (EC) are proposing a GeoDCAT-AP encoding as a Resource Description Framework (RDF) vocabulary with information content covering the union of metadata elements of the core profile of ISO 19115:2003 and those defined in the framework of the INSPIRE Directive of the European Union. This allows for a JSON-LD encoding for metadata records currently described within the INSPIRE community.

4.1.2.  CSW ebRIM AP / ISO19115 Setups

In addition to CSW ISO AP, other communities use the CSW ebRIM Application Profile (AP) OGC 07-114r4 for discovery of resources described using the same ISO19115-based metadata. A dedicated ebRIM Extension Package for CSW ebRIM was developed by the OGC members and released in 2014 (OGC 13-084r2). This standard is known as I15 Extension Package (EP) or Cataloguing of ISO19115 Metadata (CIM) EP. The extension package was originally used by the Earth Observation (EO) community to support EO collection, service and sensor discovery as described in OGC 11-035r1. A typical EO discovery workflow consists of two steps: An initial search for EO collections (similar to INSPIRE dataset series) followed by a search for EO granules (i.e., products, similar to INSPIRE datasets) belonging to the collection. The search parameters available for the granule search typically differ according to the collection, such as filtering according to cloud cover percentage only applies to collections from optical sensors. While discovery services based on the ebRIM CSW service bindings have been replaced by OpenSearch service bindings in the EO community (See CEOS-BP and OGC 13-026r9), many agencies still describe their EO collections using ISO19139(-2) metadata records. The /gmd:MD_Metadata/gmd:parentIdentifier property (ISO19139:2007), /eop:metaDataProperty/eop:EarthObservationMetaData/eop:parentIdentifier (OGC 10-157r4) property, $.properties.parentIdentifier (OGC 17-003r2) property and eo:parentIdentifier queryable (OGC 13-026r9) all reflect the hierarchical relation between the metadata record of an EO granule and the metadata record of the corresponding EO collection.

The gmd:parentIdentifier relation is also mandatory in the INSPIRE context if a higher level dataset is available in the hierarchy [5][6].

4.2.  Main use cases and requirements

Table 1 — User stories — discovery workflow

User StoryAs a …​I want to …​so that I can …​
1Metadata Consumerobtain metadata about the catalog service endpoint, including its service bindings.interact with the catalog.
2Metadata Consumeraccess the catalog service and perform requests for catalog records.discover metadata records available in the catalog.
2.1Metadata Consumeraccess the catalog service and perform search requests for catalog records matching my search criteria.discover metadata records available in the catalog.
2.2Metadata Consumeraccess the catalog service and retrieve one specific complete catalog record in a specific format.retrieve all detailed metadata information for a single record in my preferred format (XML, ISO, RDF, …).
3Metadata Publisherupload metadata records in the catalogmake them discoverable for metadata consumers.
3.1Metadata Publisherupdate or remove metadata records available in the catalogperform metadata changes.
3.2Metadata Publisherobtain metadata records available in the catalog.perform metadata changes.

Clause 4.1 of [3] lists the identified use cases that an INSPIRE Discovery Service has to fulfill to support the typical INSPIRE workflow. Such a service is known as the INSPIRE Profile of CSW ISO AP. The corresponding use case diagram is depicted below.

Figure 1 — Discovery Service Use Cases [3]

The following subsections assess whether OGC API-Records can satisfy each of these use cases and derive requirements for the additional tailoring of OGC API-Records.

4.2.1.  Use Case 1 (UC1): Get Discovery Service Metadata

A CSW catalog allows clients to retrieve service metadata from a server via the GetCapabilities operation which may contain a MetadataURL element (Req. 7 and Table 3 of [3]).

Similarly, an OGC API-Records implementation should provide the same information in the following way, to support the same workflow:

Table 2 — Discovery service metadata comparison

Extended CSW MetadataOGC API-Records Metadata
Service identification,
Service provider,
Operations metadata
Landing Page link rel=”describedby” and type=”application/vnd.iso.19139+xml” and /conformance endpoint. The hreflang attribute can be used in the link object to provide the discovery service metadata in multiple languages (Req. 6 of [3]).
Filter capabilitiesLandingPage link rel=”queryables”, type=”application/schema+json” and /queryables endpoint as per OGC 19-079r1. Similarly, CQL capabilities are to be advertised.

Recommendation 1

Statement

The discovery interface should provide discovery service metadata equivalent to the above Extended CSW Capabilities information.

4.2.2.  Use Case 2 (UC2): Discover Metadata

To implement the INSPIRE workflow, the CSW ISO AP supports the GetRecords operation as per clause 4.3.2 of [3] with following two additional parameters.

  • The language parameter: The OGC API-Records API server can provide a similar capability by supporting the usual HTTP content negotiation mechanisms and process the Accept-Language header of a request (as per clause 7.10 of OGC 17-069r3).

  • The query parameter: Supported by the filter statement of CSW ISO AP. To support similar Filter_Capabilities as can be advertised in a CSW Capabilities document, the OGC API-Records server will need to implement a subset of the draft OGC Common Query Language (CQL2) OGC 21-065 and support CQL2 filter expressions at the /collections/{collection-id}/items endpoint.

    NOTE  INSPIRE requires the Discovery Service to advertise the default language in the CSW GetCapabilities response. Proposing a similar mechanism to advertise the default language is further work. Possible approaches include:

    • advertise default language in the OGC API-Records Landing Page response;

    • advertise default language in the OGC API-Records API Definition response; and

    • use of hreflang in the link object referring to the search endpoint (/collections/{id}/items) in a Collection response.

Recommendation 2

Statement

The discovery interface should support the equivalent of the (INSPIRE) search parameters defined in clause 4.4 of [3].

When past OGC discovery interfaces were defined, INSPIRE requirements were taken into account by proposing the search parameters required by the INSPIRE discovery service. The OGC OpenSearch standard OGC 13-026r9 was tailored in this way to cover INSPIRE requirements and a dedicated INSPIRE conformance class was added. The CSW CIM EP specification was also tailored for INSPIRE requirements.

To ensure a common response format, a GetRecords request is recommended to support “application/xml” and ISO19139 as outputSchema (outputSchema=http://www.isotc211.org/2005/gmd).

Recommendation 3

Statement

The discovery interface should support access to the (original) XML-based metadata (i.e., ISO19139, ISO19139-2, ISO19115-3, etc.) through content negotiation or indirectly via an $.properties.links[] object with rel=”via” in a regular API-Records GeoJSON search response.

Recommendation 4

Statement

The discovery interface should use the media types listed in OGC13-026r9 for identifying ISO19139, ISO19139-2, or ISO19115-3 representations, i.e., “application/vnd.iso.19139+xml”, “application/vnd.iso.19139-2+xml”, and “application/vnd.iso.19115-3+xml” for content negotiation or as type attribute of the rel=”via” links.



{
"rel": "via",
"href": "https://fedeo.ceos.org/collections/series/items/PROBA.CHRIS.1A?httpAccept=application/vnd.iso.19139%2Bxml",
"type": "application/vnd.iso.19139+xml",
"title": "ISO 19139 metadata"
}

Figure 2 — Access to Original ISO Metadata File With "Via" Link From the GeoJSON Representation.

An INSPIRE discovery service has to advertise all its queryables. To achieve this capability, the OGC API-Records catalog needs to advertise its queryables via the appropriate endpoints /queryables and/or /collections/{collection-id}/queryables.

Recommendation 5

Statement

The discovery interface should support discovery of “datasets,” “dataset series,” and “services”.

Recommendation 6

Statement

The discovery interface should support GeoDCAT-AP or DCAT-AP encoding as primary metadata representation.

Recommendation 7

Statement

The discovery interface should support retrieval of records using their GeoDCAT-AP or DCAT-AP encoding in at least the following RDF serialisations: application/rdf+xml and application/ld+json. Support for text/turtle is optional.

4.2.3.  Use Case 3 (UC3): Publish Metadata

The Publish Metadata operation supports editing (insert, update, and delete) of metadata elements of resources in the catalog (push or pull metadata mechanisms). To support the INSPIRE workflow, the CSW ISO AP has to support the Transaction (push) or Harvest (pull) operation as per clause 4.3.3 of [3].

To support similar capabilities, the OGC API-Records server will need to implement the draft “OGC API — Features — Part 4: Create, Replace, Update, and Delete” OGC 20-002 standard.

NOTE  The above OGC 20-002 standard may also support editing collections available at a /collections endpoint when the resources endpoint is interpreted as {landingPageUri}/collections. This case is similar to the {landingPageUri}/processes case (Example 2).

Recommendation 8

Statement

The catalog interface should support insertion, deletion, and update of “datasets,” “dataset series,” and “services” metadata records.

Recommendation 9

Statement

The catalog interface should support insertion and updates of records using their original ISO19139 or ISO19115-3 encoding.

Recommendation 10

Statement

The catalog interface should support insertion and updates of records using their GeoDCAT-AP or DCAT-AP encoding.

Recommendation 11

Statement

The catalog interface should support insertion and updates of records using their GeoDCAT-AP or DCAT-AP encoding in at least the following RDF serialisations: application/rdf+xml and application/ld+json. Support for text/turtle is optional.

4.3.  Proposed Interface Design

In clause 6.5, the draft OGC API-Records standard defines three building blocks that each can be tailored for a specific community. The following subsections propose a tailoring of each of these building blocks to support the requirements that were identified in the previous section.

Requirement 1

Label/req/iso/record-types-1
Statement

The catalog shall support discovery resources of type series (if applicable) via one of the following mechanisms.

A

(Option 1) Via the /collections and /collections/{resource-id} endpoints.

B

(Option 2) Via the /collections/{collection-id}/items and /collections/{collection-id}/items/{resource-id} endpoints.

Requirement 2

Label/req/iso/record-types-2
Statement

The catalog shall support discovery resources of type dataset or service (if applicable) via the /collections/{collection-id}/items and /collections/{collection-id}/items/{resource-id} endpoints.

As explained above, there are two alternative ways to map series on the data model. The tailoring of the draft OGC API-Records Standard and interpretation of the requirements below depend on the selected mapping. The term series search endpoint is used to indicate the search endpoint for series search selected according to the above requirement. The terms dataset and services search endpoint apply to the search endpoints for dataset and service records (if applicable).

4.3.1.  Record Collection (Catalog) Tailoring

Section 8 of OGC 20-004 defines the schema for the collection resource as an extension of the collection schema defined in OGC API-Features and OGC API-Common — Part 2: Geospatial Data.

Recommendation 12

Statement

If additional GeoJSON properties are required in the catalog collection schema to represent ISO19139(-2) or ISO19115-3 dataset series metadata properties, they should be borrowed from the GeoDCAT-AP or DCAT-AP encoding when possible. Applicable to Option-1 only.

Recommendation 13

Statement

The catalog should support the ISO19139(-2) or ISO19115-3 metadata representations for the collection schema (via content negotiation or a query parameter, e.g., f=). This represents an additional requirements class in addition to “clause 10.3 Requirements Class GeoJSON” and “clause 10.2 Requirements Class HTML” for the catalog collection schema in OGC 20-024. Applicable to Option-1 only.

4.3.2.  Record Schema Tailoring

Section 16.1 of OGC 20-004 defines the GeoJSON (application/geo+json) encoding of the catalog record schema.

Recommendation 14

Statement

If additional GeoJSON properties are required in the catalog record schema to represent ISO19139(-2) or ISO19115-3 metadata properties, they should be borrowed from the GeoDCAT-AP or DCAT-AP encoding when possible.

NOTE  The EO Collection GeoJSON(-LD) Encoding (OGC 17-084r1) Best Practice proposes a reusable GeoJSON encoding with corresponding mapping to ISO19139(-2) and NASA UMM-C properties in its Annex C, consistent with GeoDCAT-AP via a JSON-LD context definition.

Recommendation 15

Statement

The catalog should support the ISO19139(-2) or ISO19115(-3) metadata representations for the record schema (via content negotiation or a query parameter, e.g., f=). This represents an additional requirements class in addition to “clause 16.1 Requirements Class GeoJSON” and “clause 16.3 Requirements Class HTML” for the catalog record schema.

4.3.3.  Records API Tailoring

Requirement 3

Label/req/iso/type-queryable
Statement

The OGC API-Records search endpoint shall support the queryable type, equivalent to the CSW queryable Type (MD_Metadata.hierarchyLevel) to filter (ISO19139) metadata records based on the hierarchyLevel (i.e., series, dataset, service) (See OGC 07-045r2).

Examples:

To support the search workflows using search criteria defined in Table 4 of [3], the following requirements apply.

Requirement 4

Label/req/iso/mandatory-series-queryables
Statement

The OGC API-Records series search endpoint shall support the following additional search parameters with expected data type, meaning and mapping on (ISO19139) metadata as defined in OpenSearch Extension for Earth Observation (OGC 13-026r9).

A

useLimitation.

B

accessConstraint

C

otherConstraint

D

classification

E

organisationName

F

organisationRole

G

topicCategory

H

lineage

I

keyword

J

denominator

K

distanceValue

L

distanceUOM

M

Accept-Language (header) — i.e., metadata language.

N

title

O

abstract

P

specificationTitle

Q

specificationDate

R

specificationdateType

S

degree

Requirement 5

Label/req/iso/mandatory-item-queryables
Statement

The OGC API-Records /collections/{collectionId}/items endpoint (a.k.a. dataset and service search endpoint) shall support the additional search parameters listed in the previous requirement /req/iso/mandatory-series-queryables.

Requirement 6

Label/req/iso/advertise-series-queryables
Statement

The OGC API-Records interface shall advertise the available queryables for the series search endpoint (if applicable) at the endpoint corresponding the option selected for “series” discovery (See above)

A

Via the /queryables endpoints (If Option 1 was selected).

B

Via the /collections/{collection-id}/queryables (if Option 2 was selected).

Requirement 7

Label/req/iso/advertise-item-queryables
Statement

The OGC API-Records interface shall advertise the available queryables for the dataset and service search endpoints (if applicable) at the /collections/{collection-id}/queryables endpoint.

The example below provides an example of a /queryables response advertising search parameters required for a typical INSPIRE discovery workflow.



{
"$schema": "http://json-schema.org/draft/2019-09/schema",
"title": "Available search parameters",
"type": "object",
"properties": {
"limit": {
"title": "limit",
"type": "integer"
},
"bbox": {
"title": "bbox",
"type": "array",
"minItems": 4,
"maxItems": 6,
"items": {
"type": "number"
}
},
"datetime": {
"title": "datetime",
"type": "string"
},
"externalId": {
"title": "externalId",
"type": "array",
"items": {
"type": "string"
}
},
"type": {
"title": "type",
"type": "array",
"items": {
"type": "string"
}
},
"q": {
"title": "q",
"type": "array",
"items": {
"type": "string"
}
},
"useLimitation": {
"title": "useLimitation",
"type": "string"
},
"accessConstraint": {
"title": "accessConstraint",
"type": "string",
"enum": [
"copyright",
"patent",
"trademark",
"license",
"intellectualPropertyRights",
"restricted",
"otherRestrictions"
]
},
"otherConstraint": {
"title": "otherConstraint",
"type": "string"
},
"classification": {
"title": "classification",
"type": "string",
"enum": [
"unclassified",
"restricted",
"confidential",
"secret",
"topSecret"
]
},
"organisationName": {
"title": "organisationName",
"type": "string",
"enum": [
"CEDA",
"CMEMS",
"DE/DLR",
"ESA/ESRIN",
"FR/CNES",
"JP/JAXA/EOC",
"VITO"
]
},
"organisationRole": {
"title": "organisationRole",
"type": "string",
"enum": [
"resourceProvider",
"custodian",
"owner",
"user",
"distributor",
"originator",
"pointOfContact",
"principalInvestigator",
"processor",
"publisher",
"author"
]
},
"topicCategory": {
"title": "topicCategory",
"type": "string"
},
"lineage": {
"title": "lineage",
"type": "string"
},
"keyword": {
"title": "keyword",
"type": "string"
},
"denominator": {
"title": "denominator",
"type": "string"
},
"distanceValue": {
"title": "distanceValue",
"type": "number"
},
"distanceUOM": {
"title": "distanceUOM",
"type": "string"
},
"language": {
"title": "type",
"type": "string"
},
"title": {
"title": "type",
"type": "string"
},
"abstract": {
"title": "abstract",
"type": "string"
},
"specificationTitle": {
"title": "specificationTitle",
"type": "string"
},
"specificationDate": {
"title": "specificationDate",
"type": "string",
"format": "date-time"
},
"specificationdateType": {
"title": "specificationdateType",
"type": "string",
"enum": [
"creation",
"revision",
"publication"
]
},
"degree": {
"title": "degree",
"type": "string",
"enum": [
"True",
"False",
"Null"
]
}
},
"$id": "https://tb18.cat.org/collections/series/queryables"
}

Figure 3 — Advertising INSPIRE Search Parameters Via the /queryables Response

Requirement 8

Label/req/iso/update-series
Statement

The OGC API-Records shall implement (series) metadata record insertion, update, and deletion at the /collections (Option 1) or /collections/{collection-id}/items endpoint (Option2) using the paths and HTTP methods as per OGC20-002.

Requirement 9

Label/req/iso/update-items
Statement

The OGC API-Records shall implement (dataset and service) metadata record insertion, update, and deletion at the /items endpoint using the paths and HTTP methods as per OGC20-002.

See Annex A Example 3.3 for a detailed Jupyter Notebook example using the POST operation and application/xml media type to insert a metadata record and the DELETE operation to remove the record.

The resource definition diagram below summarizes the available resources, the applicable HTTP methods, available representations, and the paths for each of the resources. Some parts of the diagram only apply when Option 1 was used for modeling (ISO) series, i.e., when /collections/{collection-id} represents a series.

Figure 4 — Resource Definition Diagram for Tailored OGC API-Records

5.  Asynchronous Communication for OGC API-Records

5.1.  Introduction

One of the goals for Testbed-18 was to contribute to asynchronous communication discussions by implementing an asynchronous catalog. The OGC Testbed-18 Call for Participation (CFP) describes asynchronous communication as scenarios where clients want to subscribe to updates for previously provided queries. Those subscribers should be informed of new or updated catalog entries (e.g., inserted by a publisher).

The designed solution described below is based on the Subscription resource which represents the mission of delivering update notification based on the requested records query and the provided delivery method.

Although the approach above does not specifically tackle the concern of queries that cannot be processed within regular HTTP time out (e.g., when the server needs encrypting), such a scenario is simply a special case of a subscription with a single update notification (when the response is available).

5.2.  Main Use Cases and Requirements

Table 3 — User Stories — Asynchronous Catalog

User StoryAs a …​I want to …​so that I can …​
21Metadata Consumersubscribe to a search request.receive additional search results in the future matching my original search criteria.
22Metadata Consumerunsubscribe to a search request subscription.stop receiving additional search results in the future.
23Metadata Consumerdefine the frequency with which I want to receive additional search results (e.g., daily).receive search result updates grouped by period.
24Metadata Consumerprovide an HTTP endpoint or email address to receive notification of additional search resultschoose the notification mechanism.
25Metadata Consumerindicate at subscription time that the server shall apply Data Centric Security (signature, encryption) to the future search responses.choose the security level for future additional search results.

The subscription interface should allow a client to subscribe to the results (and updates) of a catalog query. The subscription implies that the catalog must notify (asynchronously) the subscribers of subsequent modifications matching the query until the user unsubscribes.

In particular, the following reports and interfaces covering asynchronous interactions were reviewed and considered for the design of a solution.

  • The asynchronous support capability provided in the draft OGC API – Processes Standard involves the polling of status (supported by the Core requirements class) and the callback-driven approach (supported by the Callback requirement class) which relies on OpenAPI native capabilities (https://swagger.io/docs/specification/callbacks/).

  • The behavior models described in the OGC Publish-Subscribe White Paper (OGC 20-081) include the Delayed Response, the Standing Request, the Synchronization and the Publish-Subscribe.

  • The Simple Async mechanism proposed as an OGC API – Common extension (https://github.com/opengeospatial/ogcapi-common/tree/master/proposals/simple-async).

  • The Geosynchronization mechanism specified in the OGC OWS 7 Engineering Report — Geosynchronization service (OGC 10-069r2) describing the Subscriptions, Topics, and Publishers resources and related operations.

  • The Publish/Subscribe Interface Standard (OGC 13-131r1) that supports the core components and concepts of the Publish/Subscribe message exchange pattern with OGC Web Services.

  • The OGC Testbed-13 Asynchronous Services ER (OGC 17-028) that essentially describes the Publish-Subscribe and the status polling of the legacy OGC Web Processing Service interface.

As a starting point, the OGC API — Processes Callback approach was adapted to the API Records context as follows.

  • The behavior model is extended to support a subscriber requesting continuous update notifications about new catalog records.

  • The subscriber must provide a notification expiration time to avoid flooding a subscriber with too many callback notifications.

  • The Dismiss operation must support the cancellation of the subscription.

  • The content of the notification may either include the (updated) records or a link to these records.

While the callback could be specified in HTTP GET Catalog request, the Testbed participants reached a consensus to design a blank solution and handle the subscription creation from a dedicated HTTP POST on the resource endpoint.

5.3.  Proposed Interface Design

The following subsections propose a OGC Subscription requirement class for the OGC API-Records draft standard. The proposed interface relies on subscription resources. A subscription is a job that delivers notifications when a client subscribes to resources updates (i.e., new records or modified records).

The following flow applies to a subscription and the resulting notifications.

  • The Catalog Client (on the behalf of a signed user) submits a subscription request to the Catalog server and provides the URL to the subscribed resources and the delivery options (delivery method, expiration, schedule).

  • The Catalog server registers the subscription and returns HTTP code 201 along with the link to the created subscription.

  • Each time the server schedules a check on the subscribed records, a notification is prepared and sent to the configured receiver.

Figure 5 — Asynchronous Pattern for API Records

The interface provides operations to create, read, update, and delete subscriptions. The resource definition diagram below summarizes the applicable HTTP methods and the paths for each of the resources.

Figure 6 — Subscriptions Resources API Definition

5.3.1.  Subscription Resource Schema

A subscription is represented as the following set of properties.

  • Resources-uri: Identifier of the resources to which the user subscribes (typically a URL to catalog records).

  • Delivery: Method and target for notification deliveries formatted as protocol:address[,additional parameters] (e.g., mailto:you@ogc.org).

  • Expires: Seconds the subscription is valid (or ISO 8601 date to be discussed)/

  • Schedule: Defines the notification schedule using a cron-like format (e.g., “0 0 * * 0”).

  • Status: Indicates the state of a created subscription (e.g., started, completed, cancelled).

  • Deliveries: List the URL links to the resources that have already been delivered (in a notification).

Additional DCS properties (public-key, wrapped-dek) are detailed further.

The OpenAPI 3.0 schema subscription.yaml is represented on the class diagram below.

Figure 7 — Subscription Schema

5.3.2.  Create a Subscription

A client can create a subscription by identifying the resources for which update notifications should be sent and indicating the delivery options.

Requirement 10

Label/req/subscriptions/create
Statement

The server shall support the HTTP POST operation at the path /subscriptions. The request shall be based on the SubscriptionRequest class of the subscription.yaml schema.

Requirement 11

Label/req/subscriptions/create-success
Statement

A successful execution of the operation shall be reported as a response with a HTTP status code 201. The header of the response shall return the HTTP Location header that contains a link to the newly created subscription.

The example below illustrates a typical subscription request.



{
"resources-uri": "http://server.com/records/items?param=value",
"delivery": "http://server.com/callbackURI",
"expiry": "2025-12-10T",
"schedule": "0 0 * * 0"
}

Figure 8 — Subscription Request Example

See also Annex A Example 5.1.

Alternatively, a subscription could be requested directly when retrieving a list of catalog records. This could be achieved by extending the HTTP GET request with the relevant parameters (such as the OGC API Processes callbacks). However, the Testbed participants agreed to focus on the specific subscription endpoint in the context of the OGC API Records.

5.3.3.  Receive subscription notifications

If the subscriber provides a delivery method, then the results are communicated to the delivery endpoint in accordance with the delivery options (expiry, schedule, etc.). Also, the subscriber can specify preferences about the notification content (updated records or a link to those records) using the HTTP Prefer header as detailed below.

Requirement 12

Label/req/subscription/notification
Statement

The server shall deliver notifications when subscribed resources (identified in resources-uri) are updated (new resources or modified resources). If the request is accompanied with the HTTP Prefer header then the server SHOULD honor that preference.

A

The notification must contain a link to the resources if the subscription request is provided with the Prefer header with value ‘return=minimal’ or if the header is not present.

B

The notification must contain the list of resources if the request is accompanied with the HTTP Prefer header asserting a return=representation preference.

Requirement 13

Label/req/subscriptions/notification-delivery
Statement

The server shall send update notifications only if a delivery method is provided in the subscription. If provided, the server shall deliver notifications using the method and protocol provided in the delivery property (e.g., mailto:you@ogc.org)

Requirement 14

Label/req/subscriptions/notification-expires
Statement

If the expires property is provided, the server shall stop deliver notification starting at the indicated expiration date.

Requirement 15

Label/req/subscriptions/notification-schedule
Statement

If the schedule property is provided, the server shall deliver notification following the provided UNIX cron schedule.

5.3.4.  Retrieve a Subscription

A subscription can be retrieved to monitor the subscription status (e.g., started, completed, cancelled) and get links to the updated resources clusters that were reported by the server.

When no delivery method is specified, the subscription plays the same role as the job status document defined in OGC API Processes: The subscription can be polled for discovering updated resources.

Requirement 16

Label/req/subscriptions/subscription-get
Statement

The server shall support the HTTP GET operation at the path /subscriptions/{sub_id} to retrieve an existing subscription.

Requirement 17

Label/req/subscriptions/subscription-get-response
Statement

A successful execution of the operation shall be reported as a response with a HTTP status code 200. The content of that response shall be based upon the Subscription class of the OpenAPI 3.0 schema subscription.yaml. The deliveries array provide links to delivery units (i.e., a set of updated resources that have been prepared by the server).

Recommendation 16

Statement

The catalog should prepare the delivery units following the frequency specified in the schedule property. If an update is not detected, then no delivery unit should be prepared, and no link should be added to the deliveries array.

The example below illustrates the response of the HTTP GET request.

Figure 9 — Get Subscription Response Example

5.3.5.  Update and Delete Subscription

A subscription might be deleted using HTTP Delete or can be updated using HTTP Patch for editing any of the subscription property (e.g., delivery, schedule, public-key).

Note that the possibility to update the status of the subscription (e.g., paused) has been raised but not implemented in the scope of the project.

See also Annex A Example 5.6.

Requirement 18

Label/req/subscriptions/subscription-patch
Statement

The server shall support the HTTP PATCH operation at the path /subscriptions/{sub_id}. The request shall be based on the SubscriptionRequest class of the subscription.yaml schema, and the delivery process should be updated accordingly. The response of a successful PATCH request is 204: Done.

Requirement 19

Label/req/subscriptions/subscription-delete
Statement

The server shall support the HTTP DELETE operation at the path /subscriptions/{sub_id}. The corresponding subscription should be removed and can no longer be retrieved. The response of a successful DELETE request is 204: Done

5.3.6.  Subscription States

A tailoring of the OGC Subscription requirement was implemented for requesting an explicit subscription status update. The approach extends the existing status (started, completed, cancelled) with additional values, and proposes providing the PATCH operation to update the status of a subscription.

The subscription states as shown on diagram below include the following.

  • created: The subscription has been submitted by the client.

  • approved: The subscription endpoint has been approved (with the security code).

  • ready: The target resources (uri) are provided.

  • started: The subscription is manually started.

  • stopped: The subscription is manually stopped.

  • deleted: The subscription is deleted.

See also Annex A Example 5.4 and Example 5.5.

Figure 10 — Subscription State Diagram

The diagram reflects only explicit operations, but automated status changes might be relevant (e.g., automatically starting the subscription). Moreover, alternative flows and states can be considered such as completed for an expired subscription.

6.  Application of Data Centric Security

6.1.  Introduction

Applying Data Centric Security can be applied to the following interactions.

  • Synchronous Search Responses

  • Asynchronous Responses

  • Metadata Insertions/Updates in the Catalog

6.2.  Main Use Cases and Requirements

The table below summarizes the main use cases.

Table 4 — User Stories — Data Centric Security

User StoryAs a …​I want to …​So that I can …​
11Metadata Publisherupload plain text metadata records in the catalog.make them discoverable for metadata consumers.
12Metadata Publisherupload signed metadata records in the catalog.ensure integrity.
13Metadata Publisherupload encrypted metadata records in the catalog.ensure confidentiality and make it available to only selected metadata consumers.
14Metadata Publisherupload metadata records in the catalog combined with corresponding access rules.ensure appropriate access rights.
15Metadata Consumerchoose whether to receive metadata records in search responses as plain records, signed or encrypted assuming I have the appropriate access rights.select the appropriate security level.
16Metadata Consumerverify the signature of a metadata record part of a search response.check integrity and authenticity.
17Metadata Consumerdecrypt an encrypted metadata record which is part of a search response.process, display, etc. the metadata record content.

6.2.1.  Synchronous Responses With DCS

The API endpoints /collections/{id}/items (for item search), /collections/{id}/items/{id} (for collection search) etc.) that are subject to encrypted payloads or responses can vary. Clients can discover this through the media types supported for a specific resource (i.e. application/dcs+geo or application/jose).

In the context of an OGC API – Records implementation, the application of DCS has many similarities to the second scenario described in “Testbed-17: Data Centric Security ER” (21-020r1), which depicts the exchange of DCS-protected content from an OGC API — Features implementation. The same ER describes which metadata fields in a response allow a client to successfully decrypt the information.

6.2.1.1.  Application/DCS+GEO

According to clause 4.1 of 21-020r1, for OGC API – Features, the DCS data format can be applied as an extension to XML and JSON. Although the ISO19115 tailoring of OGC API – Records may decide to also use XML formats (see above), the focus was on a JSON approach. The response formats proposed for OGC API – Features correspond to the encrypted features in a JSON container (clause 5.2.2 of 21-020r1), based on the schema illustrated below.

figure

Figure 11 — API Features JOSE Based Containers JSON Schema (dcs+geo)

The potentially sensitive information in the data_description element can be requested with three levels of security (plain, integrity, or confidentiality) depending on the requested media type profile for application/dcs+geo. The catalog server detects that a client wants an encrypted response when it receives a request (via content negotiation) for the application/dcs+geo media type.

When provided in a JSON Web Encryption (JWE) token, the data_description element (see schema above) is encrypted with the public key of the user (i.e., client) providing the public Key Encryption Key (KEK) id previously registered at the Key Management Service (KMS).

The data is always encrypted in a JWE token using a Data Encryption Key (DEK). The kid and kurl of the DEK are included the JWE header. The kurl is a custom header parameter providing the URL to the KMS to retrieve the DEK. The definition of the DCS container in JSON is provided in clause 8 of OGC 20-021r2. The responses from an OGC API Records request (assuming the GeoJSON conformance class) encrypted in a DCS container contain “metadata” (optional housekeeping information) and “data”, with “data” representing the encrypted original OGC API Records response.

The following Data Centric Security (DCS) flow applies for synchronous search (and subscription) requests.

  • [1] The Catalog Client D114 (on the behalf of a signed in user) submits a request to the Catalog server (e.g. search request) and provides the DCS media type (f parameter), the access token, the key challenge (PIN), and the key challenge method.

  • [2] The Catalog validates the access_token, applies access control based on the bearer token, and retrieves the username and client_id associated with the user token.

  • [3] The Catalog server creates a Data Encryption Key (DEK) and then encrypts the response items using the relevant key (multiple keys might be required in case various confidentiality levels are associated to the response items).

  • [4] The Catalog registers the DEK along the client id (aud parameter), the access token, and the key_challenge to Key Management Service D115 (KMS).

  • [5] The Catalog response (DCS container) is returned to the Client.

  • [6] The client extracts the DEK kid and kurl to request the DEK. Optionally, the client might provide the kek_id of a previously registered user public key (Key Encryption Key) to request the encryption of the key.

  • [7] The Key Management Service (KMS) returns the DEK key optionally encrypted with the user private key (KEK).

  • [8] The Catalog Client decrypts the DCS container and displays the records to the user.

Figure 12 — Synchronous Responses with DCS

See Annex A Example 2.1 (/items) and Example 3.1 (/items/{item-id}) for detailed Jupyter Notebook examples using the application/dcs+geo media type.

6.2.1.2.  Application/JOSE

Instead of the above approach where the catalog server chooses the encryption key and communicates the key to the client via a reference (kid) to the KMS, a client may choose to use its own public encryption key and pass that key to the catalog server. The KMS is not used in this scenario. When the response (JOSE format) is received, the client can decrypt the response with its own private (encryption) key.

See Annex A Example 3.2 for a detailed Jupyter Notebook example using the application/jose media type defined in [RFC 7515].

The current assumption is that the /collections/{collection-id}/items and /collections/{collection-id}/items/{record-id} responses are in-scope for the above encryption. The same approach can be applied to /collections and /collections/{collection-id} if appropriate, with encrypted JSON instead of GeoJSON representations. Clients can discover which resources (URL) accept requests for the application/dcs+geo or application/jose media types as this should be advertised by the server in the OpenAPI definition of the interface or even in an OpenSearch OSDD document. This allows for a flexible use of such encrypted response capabilities by a (Catalog).

6.2.2.  Asynchronous Communication with DCS

When the notification includes links to the subscribed resources, the nominal Data Centric Security process can be applied when the resources are retrieved by the subscriber depending on the catalog implementation.

In the case where the notification includes the records, participants explored the following models for encrypting the data.

  • Using the KMS for retrieving the DEK generated by the catalog. However, Testbed participants were concerned about persisting user information on the catalog side and/or key permissions for the receiver endpoint which are not necessarily the same as the subscriber client.

  • Providing a client public key to encrypt DEK generated by the catalog.

  • Providing a DEK to the catalog generated by the client using the catalog private key.

Further recommendations are proposed to enforce DCS on the resource data when they are requested in the notification content.

Requirement 20

Label/req/subscription/dcs
Statement

If the subscriber requests resources in the notifications (HTTP Prefer header asserting a return=representation preference), then data centric security shall be applied (i.e., resources are encrypted) if the resource-uri specifies the dcs+geo format (f parameter).

A

The catalog shall encrypt the data using the DEK provided by the client and return the DEK identifier (if wrapped_dek property is provided).

B

The catalog shall generate a DEK to encrypt the data and return the DEK encrypted using the client public key (if public-key property is provided).

6.2.3.  Record Insertions With DCS

According to clause 2.3.1 of the CFP, publishers shall be able to send new or updated content to the catalog server with encrypted content that fulfills DCS principles. This implies that the catalog server acts as a (DCS) client receiving DCS encrypted content and must implement the steps a client typically applies as described in OGC 21-020r1.

6.3.  Proposed Interface Design

6.3.1.  Synchronous Responses With DCS (Encryption)

The diagram below is the proposed resource definition diagram for an OGC API-Records implementation with support for DCS (encryption).

Figure 13 — Resource Definition Diagram for OGC API-Records With DCS (Synchronous Responses)

Figure 14 — Resource Diagram /Collections/{collectionId}/Items

6.3.2.  Asynchronous Responses With DCS

As mentioned earlier, when notifications are requested for including the records (with the return-representation preference), the content must be encrypted for applying Data Centric Security.

The following flow extends the OGC API-Records asynchronous flow with DCS.

  • The Catalog Client (on the behalf of a signed user) submits a subscription request to the Catalog server (with the return-representation preference). The request includes either the public-key or wrapped-dek property (detailed further).

  • The Catalog server registers the subscription and returns HTTP code 201 along the link to the created subscription.

  • Each time the server prepares a notification, the records are encrypted depending on the selected security approach.

Figure 15 — DCS Async Sequence Diagram

6.3.2.1.  Subscriber Submits a DEK

The subscriber might submit a DEK generated locally then used by the catalog to return the resources encrypted in the notifications. The notification content is encoded in a JWE token with a header mentioning the kid (client DEK identifier) for decrypting the notification payload. The major drawback of this method is the reuse of the same encryption key for all notifications, potentially for years.

In the request, the subscriber provides the wrapped-dek property which holds the JWE token that includes the encrypted JWK encoding of the client DEK. The client DEK is encrypted with the catalog public key advertised on /.well-known/jwks.json with the attribute use set to enc.

The following subscription flow applies to a notification encryption based on a DEK generated by the client.

  • The catalog client (on the behalf of a signed user) retrieves the catalog server public key.

  • The catalog client generates the DEK and encrypts the DEK using the catalog public key.

  • The catalog client submits a subscription request to the catalog server and provides the encrypted DEK in the wrapped_dek property.

  • The catalog server decrypts the DEK with the private key.

  • For each notification, the catalog server encrypts the data records with the DEK.

  • The receiver service of the catalog client decrypts the data with the DEK.

Figure 16 — Notifications With DCS (Client Sends the DEK) Sequence Diagram

6.3.2.2.  Subscriber Submits Public Keys

The subscriber might submit a public key used to return the DEK that will be created by the catalog. The subscriber provides the public_key property which consists of a JWK public key.

In the notifications, the resources are encoded in a JWE token which includes the DEK encoded with the public key.

The following subscription flow applies to a notification encrypted based on a DEK generated by the catalog server.

  • The catalog client submits a subscription request to the Catalog server and provides a public key in the public_key property.

  • For each notification, the catalog server generates a DEK and sends the encrypted notification along with the JWE token holding the DEK encrypted with the client public key.

  • The receiver service of the catalog client decrypts the DEK with the private key, then decrypts the notification content with the DEK.

Figure 17 — Notifications with DCS (Catalog Generates the DEK) Sequence Diagram

As the solution also has be implemented using an HTTP GET operation, the recommendation below applies for the alternative operation.

Recommendation 17

Statement

When provided in an HTTP GET request, the public key used to return the DEK should be encoded using the deepObject style as per OpenAPI 3.0 – simple non-nested objects are serialized as paramName[prop1]=value1&paramName[prop2]=value2&…​

6.3.2.3.  Callback Endpoint Security Concerns

The notification endpoints (email address or HTTP(S) URL) must be validated by the service for the following reasons:

  • to prevent unsolicited content for existing endpoints; and

  • to avoid spamming servers for invalid endpoints.

Recommendation 18

Statement

The server SHOULD only deliver notifications to an email delivery endpoint if a link containing a secret code and delivered to the target email address has ben clicked by the receiver (to confirm the subscription).

Recommendation 19

Statement

The server SHOULD only deliver notifications to an HTTP(s) delivery endpoint if a TBD.

6.3.3.  Record Insertions With DCS

Publishers need to send new or updated content to the catalog server so that the interested parties can be notified as elaborated in the asynchronous communication related sections of this ER.

DCS principles might be applied to encrypt the content submitted on the catalog. This implies that the catalog server acts as a DCS client receiving DCS encrypted content, and is required to implement the steps a client typically applied as described in the Testbed-17: Data Centric Security ER (OGC 21-020r1).

For applying DCS to the OGC API-Records insert operation, Testbed participants proposed relying on the private key of the catalog. The public asynchronous encryption key can be advertised in /.well-known/jwks.json.

Recommendation 20

Statement

The records inserted in a catalog should be encoded using the catalog public key provided in the /.well-known/jwks.json endpoint (with key entry provided with attribute use set with value ‘enc’).

The cty (content type) attribute of the Javascript Object Signing and Encryption (JOSE) header (i.e., first part of the JWE) should be set to the media type of the metadata record to be inserted in the catalog. For example, the value “geo+json” corresponds to “application/geo+json”, while “vnd.iso.19139+xml” corresponds to “application/vnd.iso.19139+xml”. This allows the receiving catalog to know what it should obtain after decryption.

The sequence required for applying DCS to a catalog record is illustrated on the diagram below and includes the following steps.

  • The catalog client (publisher) retrieves the JSON Web Key Set (JWKS) containing the public key required for encrypting published content. The relevant key is the key item holding the ‘enc’ value (for encoding) in the use attribute.

  • The catalog client encrypts the content with the catalog public key and submits the request to the catalog server.

  • Typically, in an isolated secured runtime environment behind the catalog server, the submitted encrypted records are decrypted with the private key.

  • Once the decryption is achieved, the record is added to the catalog database and the catalog client receives the confirmation response.

Figure 18 — Publisher with DCS sequence diagram

See Annex A Example 3.4 for a detailed Jupyter Notebook example using the POST operation and application/jose media type for publishing a metadata record.

The above sequence can be combined with asynchronous communication as illustrated in the diagram below.

  • The catalog client (publisher) retrieves the JSON Web Key Set (JWKS) containing the public key required for encrypting published content. The relevant key is the key item holding the ‘enc’ value (for encoding) in the use attribute.

  • The catalog client receives confirmation of the processing job handling the request.

  • The catalog client encrypts the content with the catalog public key and submits the request to the catalog server.

  • Typically, in an isolated secured runtime environment behind the catalog server, the submitted encrypted records are decrypted with the private key.

  • Once the decryption is performed, the record is added to the catalog database and the callback endpoint submitted by the catalog client receives a notification.

Figure 19 — Publisher with DCS sequence diagram + Subscriber

6.3.4.  Synchronous Responses With DCS (Signatures)

To address the integrity and authenticity requirements, metadata records or catalog responses can be encoded, returned, or made available in the JWS format [RFC 7515]. The structure of the JWS token (in Compact Serialization) is a special case of a JWT token [RFC 7519].

It contains three logical parts:

  • JOSE Header

  • JWS Payload

  • JWS Signature

These are the main header properties:

Table 5 — JWS header parameter names

PropertyMeaningReference
typType — declares the IANA media type of this complete JWS. The values JOSE and JOSE+JSON are defined in the JWS specification and apply to both JWS and JWE tokens.JWT [RFC 7519]
ctyContent Type — declares the IANA media type of the secured content (the payload).JWT [RFC 7519]
jwkJSON Web KeyJWS [RFC 7515]
jkuJWK Set URLJWS [RFC 7515]
algAlgorithmJWS [RFC 7515]
kidKey ID — indication or a hint about the key, which is used to sign the message.JWS [RFC 7515]

See Annex A Example 3.5 for an example using the JWS (Compact Serialization) format. This example uses the public key included in the response to validate the signature.

To ensure that the public key is actually the expected sender’s, the signature can also be validated with the public key advertised by the sender as shown in Annex A Example 3.6.

JWS can also be serialized as JSON using the “JWS JSON Serialization”. This serialization can represent multiple signatures which is not possible with the “Compact Serialization”.

For use cases where the base64url encoding of the payload (metadata record or response) is not desired, the use of “JSON Web Signature (JWS) Unencoded Payload Option” [RFC 7797] can be considered. This option is to be further explored as future work.

A simpler approach “JWS Clear Text JSON Signature Option (JWS/CT)” [7] preserves the original JSON representation of a metadata record entirely and adds a signature key in the root of the JSON object with the value of the JWS (Compact Serialization) string (first and third part). Before computing the JWS string, the JSON object is made canonical using JCS [RFC 8785]). This option is attractive for static catalogs where metadata files are put as JSON files on cloud storage (S3). This permits the full readability of the original metadata record. This approach can for instance be applied to the following.

  • OGC API-Records metadata records and crawlable catalogs

  • OGC 17-003r2 metadata records

  • STAC item metadata records

This option is only applicable to JSON-encoded metadata records (or responses) and will be further explored in future work. Signature creation and verification for JWS/CT is shown in Annex A Example 3.7 and Example 3.8.

7.  Software Design

7.1.  Software Static Architecture

The diagram below shows the original allocation of components to the different Testbed participants.

figure

Figure 20 — Component allocation

As part of the Testbed-18 Secure, Asynchronous Catalogs task, the following client and server-side components were deployed and used for integration testing.

7.2.  Interfaces Context

The figure below shows the interactions between the various components and the interfaces that were used.

Figure 21 — Component Diagram

7.2.1.  I/F KMS — Interface with Key Management System

The interface with the Key Management System (KMS) is of particular importance as most components need to interact with the KMS. The interface is defined in detail in the corresponding Engineering Report OGC 22-014. The diagrams below give an overview of this RESTful interface in terms of its different resources.

Figure 22 — Resource Diagram (/dek)

Figure 23 — Resource Diagram (/dek/{key_id})

Figure 24 — Resource Diagram (/kek)

Figure 25 — Resource Diagram (/kek/{key_id})

7.3.  Software Components Design

7.3.1.  D112 — OGC CSW Catalog Server

Endpoint: https://cat.csiss.gmu.edu/ows18

Client Partner guide: https://cat.csiss.gmu.edu/CSW_Client-Guide.pdf

The OGC CSW Standard stipulates the interfaces for catalog services. The interfaces are divided into three categories: OGC service interface, CSW discovery interface, and CSW manager interface. Specifically, the GetCapabilities operation is the OGC service interface that provides summary information of the CSISS CSW catalog. The operations in the CSW discovery interface include GetRecords, GetRecordById, DescribeRecord, and GetDomain. The operations in the CSW manager interface include Transaction and Harvest. Asynchronous processing is supported for GetRecords and Harvest requests (via csw:ResponseHandler). The CSW server supports three modes of the Transaction operation (Insert, Update, Delete).

Unlike many other agencies that rely on commercial on-demand cloud infrastructure such as Amazon Web Service (AWS), the Center for Spatial Information Science and Systems (CSISS) developed a private cloud to provide services for EO data. The private cloud was developed using Apache Cloud stack and provides virtual machines to multiple operational services hosted by CSISS (including the CSISS CSW server in Testbed 18). Currently, there are more than 300 GPU cores, over 500GB RAM, and more than 500 TB storage, as well as a cluster of NVIDIA Tesla K80 GPUs on the server. The resources available continue to expand. To ensure the safety and reliability of operational services, all machines are hosted at the CSISS Data Center, George Mason University. Thanks to the Center’s state-of-the-art UPS systems, the data center can provide continuous power support during a power interruption. Also, the Center is monitored 24 hours a day, 7 days a week to prevent any potential risk.

figure

Figure 26 — CSISS CSW Server System Architecture

7.3.2.  D113 — OGC API-Records Catalog Server

Endpoint: https://ogc.demo.secure-dimensions.de/pycsw

Software: https://github.com/securedimensions/pycsw/tree/tb18

figure

Figure 27 — D113 - OGC API-Records Catalog User Interface

For Testbed 18, the OGC API-Records implementation provided by pyCSW (https://github.com/geopython/pycsw) was extended with the following specific functionalities.

  • Publishing of records via HTTP POST and PUT with support for different content types: application/json, application/jose (JWE format).

  • Requesting records in different DCS formats: application/jose (JWS and JWE), application/dcs+geo.

  • Support for HTTP header “Preference” to trigger asynchronous responses via the generic parameter “subscription.”

  • The Catalog Service user interface and OpenAPI contain additional functionalities that allow the different DCS formats to be requested. The responses “links” section was extended with the DCS formats.

  • The Catalog Service has implemented RFC 6750 behavior (Bearer access token use) when requesting DCS formats or when publishing a record.

  • For development support, the additional functionality is available via OpenAPI.

One of the biggest challenges was how to extend an existing open source implementation (pyCSW) so that it supports DCS without changing the original code. This was nearly achieved. Most of the functionality was included in the flask wrapper using Python decorator and additional routes (POST and PUT). Only a few changes were actually required in the “ogc/api/records.py” file, mainly to support the rendering of additional links in the link section

The implementation of the record publishing (HTTP POST and PUT) is considered a prototype for demonstration only. The implementation DOES NOT check the uploaded data for malicious / dangerous code. So, DO NOT USE IN PRODUCTION!

The actual overhead associated with producing JWE or JWS is very minimal, because a record is only a few kilobytes in size. Because of the expected record size as a few kB, all cryptographic operations take place in main memory. This approach is fine for processing a single record but already may consume noticeable main memory and produce processing latency when requesting a JWS or JWE for a collection of records. So, DO NOT USE IN PRODUCTION.

The catalog server is hosted on Gunicorn (Python WSGI server) behind NGINX on Ubuntu 22.04.

The catalog service implementation interacts with the Key Management Service to register symmetric encryption keys for producing DCS responses.

The catalog service implementation is used by the Subscription Management Service to execute triggers for created subscriptions.

7.3.3.  D114 — Catalog Client, Subscriber, Publisher

The Catalog client is a web client built using React. The client uses the oidc-client package to handle user authentication with the Authenix server and store the all-important bearer token. Users can login with the button in the top right of the header if they require access to the Records server or Records subscriptions.

The client enables users to pull documents from both the OGC API-Records and CSW implementations using a variety of formats and security schemes. Since CSW only offers the ISO format unencrypted, this is the only format the client supports for CSW implementation instances. For OGC API-Records, the user can choose between JWE and XML formats. For the JWE format, they can specify either direct or key wrap encryption.

figure

Figure 28 — React Client Endpoints

The metadata is visualized via a Leaflet map and a table which can be used to edit the Title of the metadata. Further work could be done to implement a more complete data editing/interaction system depending on the required use case, for example visualizing quicklook images, etc.

figure

Figure 29 — React Client Metadata View

The JWE security functionality is enabled by the Jose NPM library. This library provides the functionality to handle the JWKs that the KMS returns when direct encryption is requested. It also deals with the asymmetric keys submitted when the user requests using key wrap. As these keys are currently hardcoded into the demo, a full implementation of this system would need to safely store those keys on a user’s device. Keys could be generated per session, but when using this encryption method the user would not be allowed to logout and then return to the session.

The resource card row enables the user to view, store, and upload stored documents to either a CSW or an API-Records instance via the upload form.

figure

Figure 30 — React Client Upload Form

The client also provides a form for creating subscriptions to the API-Records server. This currently only allows the user to subscribe to email notifications at a fixed interval, but could be extended further in future.

figure

Figure 31 — React Client Full Page

7.3.4.  D115.1 — Authorization & Identity Management System

The Authorization and Identity Management System in OGC Testbed 18 is AUTHENIX, operated by Secure Dimensions.

7.3.5.  D115.2 — Key Management Server

The Key Management Server in the OGC Testbed 18 is identical to the Testbed 17 implementation. The details of the KMS can be found in section 5.4 of the OGC 21-020r1

7.3.6.  Jupyter Notebook Client

This client is implemented as a Jupyter Notebook. When run locally, such as using with VS-Code as depicted below, the Notebook interfaces with the Authorization & Identity Management System (D115) authenticating the user and retrieving the user’s access_token.

figure

Figure 32 — Jupyter Notebook Client interaction with D115

In addition, the client demonstrates how ISO19139 Earth Observation metadata records describing series and dataset retrieved from the ESA FedEO server (EOVOC), can be inserted for use in the OGC API Server without modification. See also Example 3.4.

figure

Figure 33 — Jupyter Notebook Client

The Notebook can be run in the Google Colaboratory environment as well as it is depicted below.

figure

Figure 34 — Jupyter Notebook Client running in Google Colab

The source code of the Jupyter Notebook is included as Annex A. The Notebook code acts as a client to many of the server components as shown below.

Figure 35 — Component Diagram Jupyter Notebook

8.  Future Work

8.1.  Asynchronous Communication

8.1.1.  Include Reference to Subscription Endpoint

Possibly use rel=’monitor’ link as defined by RFC 5989 to the /subscriptions/{subscription-id} endpoint which monitors the HTTP resource (i.e., search request) which produced the search result(s) in the search response (FeatureCollection).

Similarly, a subscription endpoint available for an OGC API-Records service should be discoverable in the landing page of the OGC API-Records service (in addition to being described in its OpenAPI definition) to allow clients to choose between the synchronous or the asynchronous interfaces.

8.1.2.  OGC API-Notification Service

Propose Webhooks for an OGC API-Notification Service specification for other services besides Records which should work with the PubSub SWG.

8.1.3.  Notification Content

The subscription prototype backend performs a periodic check as to whether the response corresponding to the resources-uri in the subscription object is identical or not to the original response. If not, then the same resources-uri is sent to the subscriber according to the delivery mechanism that was selected.

If the resources-uri corresponds to a single item (e.g., /items/{item-id}), then this means that the record content has changed. If the resources-uri corresponds to a search request (e.g., /items?…​), then this means that the (first result page) of the response has changed.

A number of improvements are possible.

  • In the case of a search request, changes should be detected that affect not only the first result page (e.g., first n results and information about total number of hits). A deletion followed by an insertion, keeping the total number of results identical, may not be detected.

  • In case resources-uri corresponds to a search request, the client should have the option to receive the actual changes, instead of a repetition of the full set of results. This is particularly useful for very large collections or searches with many results. A mechanism to receive information about deleted records is required in particular when the notification mechanism would be applied for supporting incremental harvesting. A mechanism similar to the Atom deleted-entry Element [RFC-6721] might be applied. The Open Archive Initiative Protocol for Metadata Harvesting [OAI-PMH], which is still widely used, has support for deleted records.

  • When a resource-uri corresponds to a search result, e.g., “all records with datetime overlapping with date-1 and date-2”, it might be useful to indicate in a subscription that the dates are to be interpreted as relative with respect to the actual time the subscription check is executed, instead of interpreting dates always as absolute dates.

8.1.4.  Asynchronous Patterns for OGC API Common

A significant topic for future activities should be exploring how asynchronous communications can be addressed at the OGC API Common level. In the context of other APIs, asynchronous communications must address a wider range of concerns than for OGC API Records, as show in the following examples.

  • A server might handle requests asynchronously for preparing the results (single response), or in response to certain events (multiple responses).

  • A client should specify the preferred behavior for retrieving the delayed response(s) either actively (polling pattern) or passively (push pattern requiring a listener endpoint).

The next subsections propose patterns to address general OGC API concerns related to asynchronous communications.

  • The asynchronous pattern for delayed response provides a simple solution to query (poll) a URL until the response is ready.

  • The callback pattern for delayed response complements the asynchronous pattern for specifying an endpoint for receiving (push) the response(s).

  • The OGC API Common Asynchronous requirement class is a draft that generalizes the API records asynchronous solution relying on jobs resources.

8.1.4.1.  Asynchronous Pattern for Delayed Response

Implementations of OGC APIs typically use a communication protocol pattern based on a single socket pair for sending and receiving an HTTP(S) request / response. The handling of slowly resolved queries that are not ready within the regular HTTP time out (i.e., roughly 30 seconds) can be addressed using a simple communication pattern (not implying the subscription resources solution detailed earlier).

The proposed standard RFC 7240 “Prefer Header for HTTP” recommends using the ‘Prefer’ header to indicate the server behavior preferred by the client. As already adopted by OGC API Processes, the “respond-async” preference indicates that the client prefers the server to respond asynchronously to a response. In addition, the value respond-async, wait=10 is a hint to the server that the client expects a maximum of 10 seconds to return the response following the traditional synchronous pattern.

RFC 7240 mentions that the server honoring the “respond-async” preference should return a 202 (Accepted) response as per HTTP 1.1 (RFC 7231). However, the actual behavior is unspecified, and little guidance is provided by code 202 (“The representation sent with this response ought to describe the request’s current status and point to (or embed) a status monitor that can provide the user with an estimate of when the request will be fulfilled”). For the above reason, some Testbed participants also proposed considering the alternative code 303: See Others. “See Other” is a way to redirect web applications to a new URI, particularly after a HTTP POST has been performed.

Independent of the response code, the server should return a Location header (and an optional Retry-After header) holding a link to the target requested resources. The link to the target resources can monitor the status of the previous request until the resources are available. The structure of the monitor response is custom as it needs to fit the purpose. But, to ensure that the caller is not too proactive, the server may throttle the caller via 429 (too many requests: Retry-after).

Figure 36 — Asynchronous Pattern for Delayed Response

8.1.4.2.  Callback Pattern for Delayed Response

Complementary to the asynchronous pattern described above, the request might be extended to submit an endpoint URI for receiving callback messages that contain the delayed response of the server. Indeed, as adopted by OGC API Processes, OpenAPI 3.0 provides a callback (push-based) mechanism where a subscriber-URL is passed to the API in the request. Once the resources are available, the result response is sent to the specified URL.

OpenAPI supports specifying the placeholders of the callback URI’s (potentially for a set of defined events) submitted in the request, and to define the schemas of the callback messages which must be specified in the callbacks property of the related definition of the OpenAPI operation. An example is shown below.



callbacks:
  completed:
    '{$request.header.Prefer}/callbackURI':
      post:   # Method
        requestBody: # Contents of the callback message
         
        responses:  # Expected responses
        

Figure 37 — Generic OpenAPI Definition of the callback

For expressing the callback endpoint (and options), Testbed participants highlighted one simple approach taking advantage of the Prefer header. The header might be extended with a callback token holding the (single) endpoint for callback messages. Also, in case of multiple results (based on particular events), the frequency preference can be provided in a schedule token holding a unix-cron value.

8.1.4.3.  OGC API Common Asynchronous Requirement Class

The proposed approach for a generic asynchronous requirement class relies upon the typical use of HTTP code 202. A job resource is created to monitor the execution of the request. Note that the approach is very similar and reuses most concepts from the OGC API Processes.

Recommendation 21

Label/rec/core/process-execute-honor-prefer
A

If a request is accompanied with the HTTP Prefer header asserting a respond-async preference, then the server should honor that preference and response asynchronously.

B

If a request is accompanied with the HTTP Prefer header asserting a wait preference, then the server should honor that preference in the decision to execute the process asynchronously.

C

If a request is accompanied with the HTTP Prefer header, then in the response, servers should include the HTTP Preference-Applied response header as an indication as to which ‘Prefer` tokens were honored by the server.

Recommendation 22

Label/req/async/response
A

If a request is executed asynchronously, the server should respond with an HTTP status code of 202. The server should return a Location header (and an optional Retry-After header) holding a link to the job monitoring the processing of the request.

Requirement 21

Label/req/async/job
A

The server shall support the HTTP GET operation for retrieving a long-running asynchronous job at the path /jobs/{jobID}.

B

A successful execution of the operation shall be reported as a response with a HTTP status code 200. The content of that response shall be based upon the OpenAPI 3.0 schema jobStatus.yaml.

The jobStatus schema is illustrated on the class diagram below.

Figure 38 — JobStatus Schema

Recommendation 23

Label/req/async/prefer-callback
A

If a request is accompanied with the HTTP Prefer header asserting a callback preference (endpoint URI), then the potential asynchronous response(s) should be pushed as a callback message delivered to the provided callback endpoint URI.

B

If a request is accompanied with the HTTP Prefer header asserting a callback preference and a schedule UNIX-cron value, then the potential asynchronous response(s) should be pushed in respect to the submitted schedule.

The resulting sequence diagram is provided below.

Figure 39 — Generic Asynchronous Job Sequence Diagram

The status values defined in OGC API Processes are clarified below in the context of sequential results updates (on purpose) managed by the asynchronous job.

Requirement 22

Label/req/async/job-status
A

The status of a job shall be accepted if the asynchronous job request is valid and has been queued for execution.

B

The status of a job shall be running if the provided start time has been reached.

C

The status of a job shall be failed if the asynchronous job request is not valid or if the processing of the request raised an error that prevented its completion.

D

The status of a job shall be dismissed if the asynchronous job has been dismissed through a HTTP DELETE request.

E

The status of a job shall be successful if the asynchronous job has completed or the end time has been reached.

8.2.  Data Centric Security

8.2.1.  Request for Specific Encrypted Media Type

The application/dcs+geo (JSON-based) media type as currently defined contains a data object and a metadata object. In the current document, the data object carries the encrypted payload, i.e., an encrypted catalog /items response (GeoJSON FeatureCollection) or /items/{item-id} response (GeoJSON Feature). The content of the metadata object is use-case specific and not required for decryption purposes.

While the current document assumes that the catalog responses (after decryption) are GeojSON objects, this can be generalized to allow the encrypted payload to be used to carry the encrypted representation of other metadata formats including ISO19139, ISO19139-2, ISO19115-3, etc. The cty (content type) attribute in the JOSE header of the JWE already allows the specification of the media type (omitting “application/” when no additional “/” appears) that will result after decryption.

Similarly, it should be possible for a catalog client to request an application/dcs+geo or application/jose response and additionally specify the expected content-type (e.g., ../items?cty=vnd.iso.19139+xml) the client expects to obtain after decrypting the data object included in the application/dcs+geo or the application/jose response.

8.2.2.  Generic Approach for Any OGC API

Future work should define how to apply DCS to all OGC APIs, with a JSON or XML-based container. Homogeneous solutions are preferred, allowing the use of XML or JSON encodings for all responses generated by the resources of the RESTful interface, avoiding the need to mix technologies and related tools.

8.2.3.  DCS for XML via STANAG

While the above approach would allow for returning (and encrypting) XML-based responses with the JSON-based API, organizations may want to avoid mixing XML and JSON and may prefer having XML responses for all resources of the RESTful API, using an XML container (media type) for carrying encrypted XML payloads, etc., while adopting the OGC API-Records API. The STANAG 4778 container format proposed in OGC 19-016r1 may be reused for this.

8.3.  Authentication and Authorization

Future work should include migration from access tokens in Bearer HTTP header fields to access tokens in DPoP HTTP header fields demonstrating proof of possession (DPoP) as proposed in https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop and RFC 7800.



GET /collections/datasets/items?... HTTP/1.1
   Host: catalog.org
   Accept: application/jose
   Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
   DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik
    VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR
    nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE
    QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiJlMWozVl9iS2ljOC1MQUVCIiwiaHRtIj
    oiR0VUIiwiaHR1IjoiaHR0cHM6Ly9yZXNvdXJjZS5leGFtcGxlLm9yZy9wcm90ZWN0Z
    WRyZXNvdXJjZSIsImlhdCI6MTU2MjI2MjYxOCwiYXRoIjoiZlVIeU8ycjJaM0RaNTNF
    c05yV0JiMHhXWG9hTnk1OUlpS0NBcWtzbVFFbyJ9.2oW9RP35yRqzhrtNP86L-Ey71E
    OptxRimPPToA1plemAgR6pxHF8y6-yqyVnmcw6Fy1dqd-jfxSYoMxhAJpLjA

Figure 40 — Example Request With DPoP-Bound Access Token

8.4.  DCS and Streaming

During previous OGC Testbeds, Data Centric Security was applied to different OGC APIs and Data Encoding Standards. The synchronous characteristics of OGC APIs introduce the requirement that the maximum latency of responses is limited by the socket timeout or by the acceptance to wait by the user. To keep the response waiting time short (before the first response byte is sent to the client) it is important that the data encoding can be streamed. Streaming a resource has the advantage that the first byte is more or less sent to the client immediately after the request has been received by the server. The full response is then transferred using chunk encoding. This technique reduces the burden on the server, as memory and disk space does not limit the total size of the data to be processed.

Work in previous testbeds determined that data encoding using the OGC GeoPackage Standard cannot be streamed as the underlying SQLite file format requires that the GeoPackage is processed on the server in full before the first byte is transferred to the client. However, there are other encodings that can be streamed: A GeoJSON feature collection, for example, can be produced and transferred using chunk encoding.

The research question should be addressed in the context of DCS in which geospatial data encoding is streaming-ready and can be used in combination with DCS. For example, is it possible to produce a JWS or JWE containing a feature collection in chunks to minimize the burden on the server’s memory and disk space? Is it possible to create a STANAG 4774/4778 response in XML or JSON based on chunks? Is it possible to use a similar protocol like HLS (RFC 8216) to stream large volumes of encrypted data? Is it possible to support streams and byte ranges for encrypted data?

So a future task could be to study OGC Encoding Standards and determine their streaming capabilities and recommend their use with and without DCS applied based on prototype implementations.

8.5.  DCS in Production

Both previous Testbeds and this one introduced DCS building blocks that extend the typical geodata infrastructure architectures with specific services: Authentication, Key Management, and the Subscription Service. The latter was introduced as a generic solution to handle synchronous to asynchronous communication bridging supporting WebPush and Web Callback including security and email.

To operate the architecture and APIs in a production environment, it is important to not only have covered the green flow of information. Software engineers also should consider the red flow: Which vulnerabilities exist in the protocols, APIs, and implementations that may enable an adversary to attack certain parts of the system.

For example, the use of (simple) Bearer access tokens on the Key Management System introduces the vulnerable to token replay attacks. An attacker, in possession of an active access token from another user could obtain all keys of that the user. Even worse, perhaps, delete existing keys. Other vulnerabilities may be introduced by implementations that support the user’s ability to upload data. In these cases, implementation vulnerabilities like SQL or XSS code injection may exist that can cause data or key breach.

The research question would be to determine what vulnerabilities exist in the current Testbed DCS architecture and in existing open-source implementations by applying security best practices from the IETF (e.g., 6819), W3C, and others. For example the security recommendation for using Bearer access tokens (draft RFC ‘OAuth 2.0 Security Best Current Practice’) introduce various attack vectors. Can these attack vectors be applied to the DCS architecture and what harm would they do if successfully executed?

Another research question is related to performance and scalability. The ultimate aspect for scalability is to keep the server side (upstream applications) stateless and to reduce burden on the resources to the minimum. Can that be achieved with the current DCS architecture? Which limitations and implications to scalability and performance exist?

8.6.  Demonstrating Proof of Possession Access Token

The use of bearer access tokens is widely adopted but vulnerabilities to misuse stolen access tokens introduce a threat to DCS: Once a user has gotten an access token, it can be used with no further proof. So for example, a stolen active access token can be used for obtaining sensitive (encrypted) information and data encryption keys. This jeopardizes all efforts put into DCS.

The use of OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP) as defined in the IETF draft standard1 thwarts the successful use of stolen access tokens.

Future work should concentrate on studying the principles for using DPoP access (and refresh) tokens on a DCS architecture as outlined in Testbed 18. In particular, the use of DPoP access tokens bound to a resource URI or tagged for one time use should be studied and implemented with the DCS Server and the KMS to demonstrate the improvement over the use of bearer access tokens. This may require operating two infrastructures in parallel; one that operates bearer access tokens and one that operates DPoP access tokens. Successfully executed attacks with bearer access tokens should not be possible with the infrastructure that is based on DPoP.

8.7.  My-(OGC) API

Leveraging DCS, it is possible to manage sensitive data (features) and metadata (records). Any publishing of records or features should be associated with a user. That user would have the authority over how to preserve continuous sensitivity / integrity. So, the end-to-end sensitivity / authenticity should be supported via OGC APIs.

Is it possible to introduce the concept of ownership for OGC APIs? Should the owner of a resource have the authority over the resource’s protection? Furthermore, queries for “my” resources and “Jane’s resources” would be possible. This would be an important step towards the use of OGC APIs in Citizen Science.

What would be required to apply the “my” characteristics to OGC APIs and, in particular, DCS extensions?


Annex A
(informative)
Notebook Secure Catalog

By Y. Coene, C. Noel (Spacebel s.a.), A. Matheus (Secure Dimensions GmbH), 21 October 2022

%pip install pyjwt
%pip install folium
%pip install jsonpath-ng
%pip install jcs

import json, requests, xml
from xml.dom import minidom
from xml.etree import ElementTree
from IPython.display import Markdown as md
import folium

# Verification of SSL certificate.
verify_ssl = True

endpoint_csw = 'https://cat.csiss.gmu.edu/ows18/csw'
endpoint_api_records = 'https://ogc.demo.secure-dimensions.de/pycsw'
endpoint_collection = endpoint_api_records + '/collections/metadata:main'
endpoint_items = endpoint_collection + '/items'
endpoint_queryables = endpoint_collection + '/queryables'

# URL to an item inserted in the catalog before.
endpoint_item = endpoint_items + '/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001'
endpoint_subscriptions = 'https://ogc.demo.secure-dimensions.de/sms/subscriptions'

def add_feature_to_map( m, fdata ):
  # fdata is JSON dictionary representing a Feature
  # modifies the map 'm'

  key = 'geometry'
  if key in fdata:
        c = fdata[key]['coordinates']

        # create string with coordinates without separators
        polygon=str(c).translate(str.maketrans('','','[],'))
        list1 = polygon.split()

        points = []
        for i in range(0,len(list1),2):
          points = points + [ (float(list1[i+1]), float(list1[i])) ]

        folium.FitBounds(points, padding=(100,100)).add_to(m)
        folium.Polygon(points, popup=str(fdata), tooltip=fdata['id']).add_to(m)

  return

def show_on_map( data ):
  # data is JSON dictionary representing a FeatureCollection or Feature

  center = [38.128, 2.588]
  m = folium.Map(location=center,zoom_start=2)
  folium.LayerControl().add_to(m)

  key = 'geometry'
  if key in data:
    add_feature_to_map(m, data)
    return m

  # contains featurecollection or feature
  key = 'features'
  if key in data:
    n = len(data[key])
    if (len(data[key])<1) : return m

    key = 'geometry'
    j=0
    while (j<n):
      fdata = data['features'][j]  # use current feature of collection

      add_feature_to_map(m, fdata)
      j=j+1
  return m

Figure A.1

Requirement already satisfied: pyjwt in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (2.4.0)

[notice] A new release of pip available: 22.1.2 -> 22.3
[notice] To update, run: python.exe -m pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Requirement already satisfied: folium in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (0.12.1.post1)
Requirement already satisfied: jinja2>=2.9 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from folium) (3.1.2)
Requirement already satisfied: numpy in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from folium) (1.21.4)
Requirement already satisfied: branca>=0.3.0 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from folium) (0.5.0)
Requirement already satisfied: requests in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from folium) (2.26.0)
Requirement already satisfied: MarkupSafe>=2.0 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from jinja2>=2.9->folium) (2.1.1)
Requirement already satisfied: idna<4,>=2.5 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from requests->folium) (2.10)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from requests->folium) (1.25.10)Note: you may need to restart the kernel to use updated packages.
Requirement already satisfied: certifi>=2017.4.17 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from requests->folium) (2020.6.20)
Requirement already satisfied: charset-normalizer~=2.0.0 in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from requests->folium) (2.0.7)

[notice] A new release of pip available: 22.1.2 -> 22.3
[notice] To update, run: python.exe -m pip install --upgrade pip

Requirement already satisfied: jsonpath-ng in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (1.5.3)
Requirement already satisfied: six in c:\users\yvesc\appdata\roaming\python\python38\site-packages (from jsonpath-ng) (1.15.0)
Requirement already satisfied: ply in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (from jsonpath-ng) (3.11)
Requirement already satisfied: decorator in c:\users\yvesc\appdata\roaming\python\python38\site-packages (from jsonpath-ng) (4.4.2)

[notice] A new release of pip available: 22.1.2 -> 22.3
[notice] To update, run: python.exe -m pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.
Requirement already satisfied: jcs in c:\users\yvesc\appdata\local\programs\python\python38\lib\site-packages (0.2.1)

[notice] A new release of pip available: 22.1.2 -> 22.3
[notice] To update, run: python.exe -m pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.

Figure A.2

A.1.  D115 (Identity Mgt System) authentication

if 'google.colab' in str(get_ipython()):
    # Running in Google Colab
    access_token = input("Enter access token obtained from https://ogc.demo.secure-dimensions.de/token-app/ :")
else:
    # Not running in Google Colab
    # Authenticate via Notebook from Secure Dimensions to obtain the "access_token".
    %run ./authenix.ipynb

Figure A.3

Random string of length 4 is: jghh
Listening on port 8008 ...
GET /?code=9dfdd77a5e8936aea35c99995ec4918d43344e45&state=None HTTP/1.1
Host: 127.0.0.1:8008
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
sec-ch-ua: "Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8


Warning: state does not match!
9dfdd77a5e8936aea35c99995ec4918d43344e45

Figure A.4

A.1.1.  D115 (Identity Mgt System) Get access token

access_token

Figure A.5

'4e6e701e0eb6a7d13e76b33da136fa07a2c4d7fc'

Figure A.6

A.2.  D113 (OGC API-Records) without DCS

A.2.1.  D113 GET /items without DCS (GeoJSON)

Example: 1.1
> Access the OGC API-Records D113 /items without DCS (GeoJSON)

response = requests.get(endpoint_items + '?limit=2&offset=8',
    verify=bool(verify_ssl),
    headers={'Accept': 'application/geo+json'})

data = json.loads(response.text)
jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

Figure A.7

{
  
"type": "FeatureCollection",
  
"features": [
     
{
        
"id": "9d075d6f-a85a-18fa-1f51-ced8-ef7c-5bce-a91eee54",
        
"type": "Feature",
        
"geometry": {
           
"type": "Polygon",
           
"coordinates": [
              
[
                 
[
                    
2.52,
                    
50.64
                 
],
                 
[
                    
2.52,
                    
51.51
                 
],
                 
[
                    
5.94,
                    
51.51
                 
],
                 
[
                    
5.94,
                    
50.64
                 
],
                 
[
                    
2.52,
                    
50.64
                 
]
              
]
           
]
        
},
        
"properties": {
           
"externalId": "9d075d6f-a85a-18fa-1f51-ced8-ef7c-5bce-a91eee54",
           
"datetime": "2022-07-01",
           
"start_datetime": null,
           
"end_datetime": null,
           
"recordUpdated": "2022-07-21T22:40:13Z",
           
"type": "service",
           
"created": "2013-05-27",
           
"updated": "2022-07-01",
           
"title": "WMS Vlaamse Landmaatschappij",
           
"description": "Web Map Service met data van de Vlaamse Landmaatschappij.",
           
"keywords": [
              
"OGC:WMS",
              
"bodemeenheid",
              
"bodemkaart",
              
"gegeneraliseerde bodemkaart voor Vlaanderen",
              
"infiltratiekenmerk",
              
"kwel",
              
"kwetsbaarheid",
              
"landinrichting",
              
"landschapseenheid",
              
"plattelandsbeleid",
              
"reli\u00ebf",
              
"ruimtelijke structuren in Vlaanderen",
              
"inrichtingsproject",
              
"landinrichtingsplan",
              
"landinrichtingsproject",
              
"onderzoek",
              
"planprogramma",
              
"vastgesteld",
              
"afbakening",
              
"planbegeleidingsgroep",
              
"inrichtingsnota",
              
"recht van voorkoop",
              
"rvv",
              
"voorkoopgebied",
              
"voorkooprecht",
              
"blokgrens",
              
"kavelplan",
              
"landeigendom",
              
"ruilverkaveling",
              
"ruilverkavelingsproject",
              
"sectie",
              
"gebruiksruil",
              
"infrastructuurwerken",
              
"natuurbehoud",
              
"natuurinrichting",
              
"natuurinrichtingsproject",
              
"gebied met recht van voorkoop",
              
"focusgebied",
              
"grondwater",
              
"mestdecreet",
              
"mestactieplan",
              
"nitraat",
              
"nitraatconcentratie",
              
"nitraatresidu",
              
"nitraatresidudrempelwaarde",
              
"nitraatresidustaal",
              
"oppervlaktewater",
              
"overschrijding",
              
"waterkwaliteit",
              
"beheerovereenkomst",
              
"agromilieu-klimaatmaatregel",
              
"ecosysteemdienst",
              
"plattelandsontwikkeling",
              
"landbouwbeleid",
              
"PDPO",
              
"GLB",
              
"agrobiodiveristeit",
              
"gebiedstype"
           
],
           
"associations": [
              
{
                 
"href": "https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms?service=WMS&request=getcapabilities",
                 
"name": "Capabilities van de webdienst WMS Vlaamse Landmaatschappij",
                 
"description": null,
                 
"type": "OGC:WMS",
                 
"rel": "OGC:WMS"
              
},
              
{
                 
"href": "https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms",
                 
"name": null,
                 
"description": null,
                 
"type": null,
                 
"rel": null
              
},
              
{
                 
"href": "https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms",
                 
"name": null,
                 
"description": null,
                 
"type": null,
                 
"rel": null
              
},
              
{
                 
"href": "https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms",
                 
"name": null,
                 
"description": null,
                 
"type": null,
                 
"rel": null
              
}
           
],
           
"extent": {
              
"spatial": {
                 
"bbox": [
                    
[
                       
2.52,
                       
50.64,
                       
5.94,
                       
51.51
                    
]
                 
],
                 
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
              
}
           
}
        
},
        
"links": [
           
{
              
"rel": "via",
              
"type": "application/xml",
              
"title": "This document as XML",
              
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/9d075d6f-a85a-18fa-1f51-ced8-ef7c-5bce-a91eee54?f=xml",
              
"hreflang": "en-US"
           
}
        
],
        
"assets": {}
     
},
     
{
        
"id": "PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001",
        
"type": "Feature",
        
"geometry": {
           
"type": "Polygon",
           
"coordinates": [
              
[
                 
[
                    
3.07,
                    
51.29
                 
],
                 
[
                    
3.07,
                    
51.39
                 
],
                 
[
                    
3.28,
                    
51.39
                 
],
                 
[
                    
3.28,
                    
51.29
                 
],
                 
[
                    
3.07,
                    
51.29
                 
]
              
]
           
]
        
},
        
"properties": {
           
"externalId": "PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001",
           
"datetime": "2022-06-30T14:09:50",
           
"start_datetime": "2018-10-05T13:46:00Z",
           
"end_datetime": "2018-10-05T13:50:00Z",
           
"recordUpdated": "2022-07-21T22:40:13Z",
           
"type": "dataset",
           
"created": "2019-05-22",
           
"updated": "2022-06-30T14:09:50",
           
"title": "Proba CHRIS Level 1A",
           
"description": "CHRIS acquires a set of up to five images of each target during each acquisition sequence, these images are acquired when Proba-1 is pointing at distinct angles with respect to the target. CHRIS Level 1A products (supplied in HDF data files, version 4.1r3) include five formal CHRIS imaging modes, classified as modes 1 to 5: \u2022 MODE 1: Full swath width, 62 spectral bands, 773nm / 1036nm, nadir ground sampling distance 34m @ 556km \u2022 MODE 2 WATER BANDS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \u2022 MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \u2022 MODE 5 LAND CHANNELS: Half swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km  All Proba-1 passes are systematically acquired according to the current acquisition plan, CHRIS data are processed every day to Level 1A and made available to ESA users. Observation over a new specific area can be performed by submitting the request to add a new site to the acquisition plan.",
           
"associations": [
              
{
                 
"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001.SIP.ZIP",
                 
"name": "Download",
                 
"description": null,
                 
"type": "WWW:DOWNLOAD",
                 
"rel": "WWW:DOWNLOAD"
              
},
              
{
                 
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001.SIP.ZIP_BID.PNG",
                 
"name": "QUICKLOOK",
                 
"description": null,
                 
"type": null,
                 
"rel": null
              
},
              
{
                 
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001.SIP.ZIP_TIMG.jpg",
                 
"name": "THUMBNAIL",
                 
"description": null,
                 
"type": null,
                 
"rel": null
              
}
           
],
           
"extent": {
              
"spatial": {
                 
"bbox": [
                    
[
                       
3.07,
                       
51.29,
                       
3.28,
                       
51.39
                    
]
                 
],
                 
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
              
}
           
}
        
},
        
"links": [
           
{
              
"rel": "via",
              
"type": "application/xml",
              
"title": "This document as XML",
              
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?f=xml",
              
"hreflang": "en-US"
           
}
        
],
        
"assets": {}
     
}
  
],
  
"links": [
     
{
        
"rel": "alternate",
        
"type": "application/dcs+geo",
        
"title": "This document as DCS + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?limit=2&offset=8&f=dcs+geo",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose",
        
"title": "This document as JOSE + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?limit=2&offset=8&f=jose",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose;profile=jws",
        
"title": "This document as JWS",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?limit=2&offset=8&f=jws",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "self",
        
"type": "application/geo+json",
        
"title": "This document as GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?f=json",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "text/html",
        
"title": "This document as HTML",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?f=html",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "collection",
        
"type": "application/json",
        
"title": "Collection URL",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main",
        
"hreflang": "en-US"
     
},
     
{
        
"type": "application/geo+json",
        
"rel": "prev",
        
"title": "items (prev)",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?offset=6",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "next",
        
"type": "application/geo+json",
        
"title": "items (next)",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?offset=10",
        
"hreflang": "en-US"
     
}
  
],
  
"numberMatched": 39,
  
"numberReturned": 2,
  
"bbox": [
     
2.52,
     
50.64,
     
5.94,
     
51.51
  
]
}

Figure A.8

show_on_map(data)

Figure A.9

Make this Notebook Trusted to load map: File → Trust Notebook

A.2.2.  D113 GET /items without DCS (XML)

Example: 1.2
> Access the OGC API-Records D113 /items without DCS (XML) is not supported.

response = requests.get(endpoint_items + '?f=xml',
    verify=bool(verify_ssl),
    headers={})
# headers={'Accept': 'application/xml'})

response.text

# xmlstr = minidom.parseString(response.text).toprettyxml(indent='  ',newl='')
# md("```xml\n" + xmlstr + "\n```\n")

Figure A.10

'{"type": "FeatureCollection", "features": [{"id": "05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99", "type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[2.53, 50.67], [2.53, 51.51], [5.92, 51.51], [5.92, 50.67], [2.53, 50.67]]]}, "properties": {"externalId": "05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99", "datetime": "2022-04-12", "start_datetime": "2013-11-28", "end_datetime": "1900-01-01", "recordUpdated": "2022-07-21T22:40:13Z", "type": "series", "created": "2021-09-15", "updated": "2022-04-12", "title": "Interessante plaatsen (POI)", "description": "Datasetreeks van datasets met interessante plaatsen", "associations": [{"href": "https://geoservices.informatievlaanderen.be/overdrachtdiensten/POI/wfs?service=WFS&#x26;version=2.0.0&#x26;request=GetCapabilities&#x22;, &#x22;name&#x22;: null, &#x22;description&#x22;: &#x22;WFS Interessante plaatsen&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-2.0.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-2.0.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/POI/wfs?request=GetFeature&#x26;version=2.0.0&#x26;typename=POI:POI&#x26;count=1&#x22;, &#x22;name&#x22;: &#x22;POI:POI&#x22;, &#x22;description&#x22;: &#x22;Points of Interest&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-2.0.0-http-get-feature&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-2.0.0-http-get-feature&#x22;}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.53, 50.67, 5.92, 51.51]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;240cc7bc-21c0-442d-aa9a-03530e3bcd08&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.53, 50.67], [2.53, 51.51], [5.92, 51.51], [5.92, 50.67], [2.53, 50.67]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;240cc7bc-21c0-442d-aa9a-03530e3bcd08&#x22;, &#x22;datetime&#x22;: &#x22;2022-04-12&#x22;, &#x22;start_datetime&#x22;: &#x22;2018-06-27&#x22;, &#x22;end_datetime&#x22;: &#x22;2018-07-19&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;created&#x22;: &#x22;2015-07-01&#x22;, &#x22;updated&#x22;: &#x22;2022-04-12&#x22;, &#x22;title&#x22;: &#x22;Orthobeeldvorming - OMZ&#x22;, &#x22;description&#x22;: &#x22;Dit product is de moza\\u00efek van de zomerluchtopnamen 2018 (17 juni tot en met 1 juli 2018) zoals bedoeld in het INSPIRE thema Orthobeeldvorming.\\n\\nDe orthofotomoza\\u00efek is beschikbaar onder de vorm van een echte kleurencomposiet (RGB), een kleur-infraroodcomposiet (CIR) en een panchromatisch beeld (PAN).&#x22;, &#x22;keywords&#x22;: [&#x22;ORTHOFOTO&#x22;, &#x22;VLAAMSE GEWEST&#x22;, &#x22;ORTHOFOTO\&#x27;S&#x22;, &#x22;KLEURENORTHOFOTO\&#x27;S&#x22;, &#x22;KLEURENORTHO\&#x27;S&#x22;, &#x22;AGIV-PRODUCT&#x22;, &#x22;ORTHO\&#x27;S&#x22;, &#x22;DIGITALE ORTHOFOTO\&#x27;S&#x22;, &#x22;ORTHOFOTOBEDEKKING&#x22;, &#x22;LUCHTOPNAMEN&#x22;, &#x22;ORTHOFOTOPRODUCTIE&#x22;, &#x22;ORTHOFOTOPLANS&#x22;, &#x22;ORTHO&#x22;, &#x22;KLEURENORTHOFOTOMOZA\\u00cfEK&#x22;, &#x22;ORTHOFOTOMOZA\\u00cfEK&#x22;], &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/raadpleegdiensten/oi/wms?REQUEST=GetCapabilities&#x26;SERVICE=WMS&#x26;VERSION=1.3.0&#x22;, &#x22;name&#x22;: &#x22;Orthobeeldvorming&#x22;, &#x22;description&#x22;: &#x22;INSPIRE-compatibele raadpleegdienst (Initial Operating Capability) met lagen uit INSPIRE Annex II Thema Orthobeeldvorming (geharmoniseerde data).&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/raadpleegdiensten/oi/wms?SERVICE=WMS&#x26;REQUEST=GetMap&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;VERSION=1.3.0&#x26;LAYERS=OI.OrthoimageCoverage.OMZ.RGB&#x26;WIDTH=1920&#x26;HEIGHT=816&#x26;CRS=EPSG:3857&#x26;BBOX=399007.9156516319,6577502.008692471,399581.1933637719,6577745.651720131&#x22;, &#x22;name&#x22;: &#x22;OI.OrthoimageCoverage.OMZ.RGB&#x22;, &#x22;description&#x22;: &#x22;Orthofotomoza\\u00efek, middenschalig, zomeropnamen, kleur, 2018, Vlaanderen&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/raadpleegdiensten/oi/wms?SERVICE=WMS&#x26;REQUEST=GetMap&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;VERSION=1.3.0&#x26;LAYERS=OI.OrthoimageCoverage.OMZ.PAN&#x26;WIDTH=1920&#x26;HEIGHT=816&#x26;CRS=EPSG:3857&#x26;BBOX=399007.9156516319,6577502.008692471,399581.1933637719,6577745.651720131&#x22;, &#x22;name&#x22;: &#x22;OI.OrthoimageCoverage.OMZ.PAN&#x22;, &#x22;description&#x22;: &#x22;Orthofotomoza\\u00efek, middenschalig, zomeropnamen, panchromatisch, 2018, Vlaanderen&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/raadpleegdiensten/oi/wms?SERVICE=WMS&#x26;REQUEST=GetMap&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;VERSION=1.3.0&#x26;LAYERS=OI.OrthoimageCoverage.OMZ.CIR&#x26;WIDTH=1920&#x26;HEIGHT=816&#x26;CRS=EPSG:3857&#x26;BBOX=399007.9156516319,6577502.008692471,399581.1933637719,6577745.651720131&#x22;, &#x22;name&#x22;: &#x22;OI.OrthoimageCoverage.OMZ.CIR&#x22;, &#x22;description&#x22;: &#x22;Orthofotomoza\\u00efek, middenschalig, zomeropnamen, kleur-infrarood, 2018, Vlaanderen&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/overdrachtdiensten/oi-omz/wcs?service=WCS&#x26;version=2.0.1&#x26;request=GetCapabilities&#x22;, &#x22;name&#x22;: &#x22;Orthobeeldvorming - OMZ&#x22;, &#x22;description&#x22;: &#x22;INSPIRE-compatibele overdrachtdienst (Initial Operating Capability) met zomerluchtopnamen uit INSPIRE Annex II Thema Orthobeeldvorming (geharmoniseerde data).&#x22;, &#x22;type&#x22;: &#x22;OGC:WCS-2.0.1-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WCS-2.0.1-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/overdrachtdiensten/oi-omz/wcs?SERVICE=WCS&#x26;VERSION=2.0.1&#x26;request=GetCoverage&#x26;CRS=EPSG:4258&#x26;subset=y,http://www.opengis.net/def/crs/EPSG/0/4258(50.7461,50.9108)&#x26;subset=x,http://www.opengis.net/def/crs/EPSG/0/4258(4.2548,4.5418)&#x26;scalefactor=50&#x26;COVERAGEID=OI.OrthoimageCoverage.OMZ.RGB&#x26;FORMAT=image/tiff&#x26;RESPONSE_CRS=EPSG:31370&#x22;, &#x22;name&#x22;: &#x22;OI.OrthoimageCoverage.OMZ.RGB&#x22;, &#x22;description&#x22;: &#x22;Orthofotomoza\\u00efek, middenschalig, zomeropnamen, kleur, 2018, Vlaanderen&#x22;, &#x22;type&#x22;: &#x22;OGC:WCS-2.0.1-http-get-coverage&#x22;, &#x22;rel&#x22;: &#x22;OGC:WCS-2.0.1-http-get-coverage&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/overdrachtdiensten/oi-omz/wcs?SERVICE=WCS&#x26;VERSION=2.0.1&#x26;request=GetCoverage&#x26;CRS=EPSG:4258&#x26;subset=y,http://www.opengis.net/def/crs/EPSG/0/4258(50.7461,50.9108)&#x26;subset=x,http://www.opengis.net/def/crs/EPSG/0/4258(4.2548,4.5418)&#x26;scalefactor=50&#x26;COVERAGEID=OI.OrthoimageCoverage.OMZ.PAN&#x26;FORMAT=image/tiff&#x26;RESPONSE_CRS=EPSG:31370&#x22;, &#x22;name&#x22;: &#x22;OI.OrthoimageCoverage.OMZ.PAN&#x22;, &#x22;description&#x22;: &#x22;Orthofotomoza\\u00efek, middenschalig, zomeropnamen, panchromatisch, 2018, Vlaanderen&#x22;, &#x22;type&#x22;: &#x22;OGC:WCS-2.0.1-http-get-coverage&#x22;, &#x22;rel&#x22;: &#x22;OGC:WCS-2.0.1-http-get-coverage&#x22;}, {&#x22;href&#x22;: &#x22;https://inspire.informatievlaanderen.be/overdrachtdiensten/oi-omz/wcs?SERVICE=WCS&#x26;VERSION=2.0.1&#x26;request=GetCoverage&#x26;CRS=EPSG:4258&#x26;subset=y,http://www.opengis.net/def/crs/EPSG/0/4258(50.7461,50.9108)&#x26;subset=x,http://www.opengis.net/def/crs/EPSG/0/4258(4.2548,4.5418)&#x26;scalefactor=50&#x26;COVERAGEID=OI.OrthoimageCoverage.OMZ.CIR&#x26;FORMAT=image/tiff&#x26;RESPONSE_CRS=EPSG:31370&#x22;, &#x22;name&#x22;: &#x22;OI.OrthoimageCoverage.OMZ.CIR&#x22;, &#x22;description&#x22;: &#x22;Orthofotomoza\\u00efek, middenschalig, zomeropnamen, kleur-infrarood, 2018, Vlaanderen&#x22;, &#x22;type&#x22;: &#x22;OGC:WCS-2.0.1-http-get-coverage&#x22;, &#x22;rel&#x22;: &#x22;OGC:WCS-2.0.1-http-get-coverage&#x22;}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.53, 50.67, 5.92, 51.51]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/240cc7bc-21c0-442d-aa9a-03530e3bcd08?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;6cc019a5-0a3d-41c5-b4d9-86917fb0eefc&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[-180.0, -90.0], [-180.0, 90.0], [180.0, 90.0], [180.0, -90.0], [-180.0, -90.0]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;6cc019a5-0a3d-41c5-b4d9-86917fb0eefc&#x22;, &#x22;datetime&#x22;: &#x22;2011-05-17&#x22;, &#x22;start_datetime&#x22;: null, &#x22;end_datetime&#x22;: null, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;updated&#x22;: &#x22;2011-05-17&#x22;, &#x22;title&#x22;: &#x22;pycsw record&#x22;, &#x22;description&#x22;: &#x22;Sample metadata record&#x22;, &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[-180.0, -90.0, 180.0, 90.0]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/6cc019a5-0a3d-41c5-b4d9-86917fb0eefc?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;70c663ac-ff3e-4b9a-9867-bb22bbdfcf6d&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.53, 50.67], [2.53, 51.51], [5.92, 51.51], [5.92, 50.67], [2.53, 50.67]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;70c663ac-ff3e-4b9a-9867-bb22bbdfcf6d&#x22;, &#x22;datetime&#x22;: &#x22;2022-04-12&#x22;, &#x22;start_datetime&#x22;: &#x22;2009-05-29&#x22;, &#x22;end_datetime&#x22;: &#x22;1900-01-01&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;series&#x22;, &#x22;created&#x22;: &#x22;2016-08-03&#x22;, &#x22;updated&#x22;: &#x22;2022-04-12&#x22;, &#x22;title&#x22;: &#x22;Groenkaart Vlaanderen&#x22;, &#x22;description&#x22;: &#x22;Bundeling van de datasets die een overzicht geven van het groen in Vlaanderen voor bepaalde jaren.&#x22;, &#x22;keywords&#x22;: [&#x22;stedelijk groen&#x22;, &#x22; landbouwgebruiksperceel&#x22;, &#x22; boswijzer&#x22;, &#x22; landbouw&#x22;], &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;http://www.geopunt.be/download?container=groenkaart&#x26;title=Groenkaart%20Vlaanderen&#x22;, &#x22;name&#x22;: &#x22;Groenkaart Vlaanderen&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:DOWNLOAD-1.0-http--download&#x22;, &#x22;rel&#x22;: &#x22;WWW:DOWNLOAD-1.0-http--download&#x22;}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.53, 50.67, 5.92, 51.51]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/70c663ac-ff3e-4b9a-9867-bb22bbdfcf6d?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20030920T110000_N51-028_E002-088_0001&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.78, 51.22], [2.78, 51.32], [2.99, 51.32], [2.99, 51.22], [2.78, 51.22]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20030920T110000_N51-028_E002-088_0001&#x22;, &#x22;datetime&#x22;: &#x22;2022-06-30T14:10:28&#x22;, &#x22;start_datetime&#x22;: &#x22;2003-09-20T11:00:00Z&#x22;, &#x22;end_datetime&#x22;: &#x22;2003-09-20T11:04:00Z&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;created&#x22;: &#x22;2019-05-22&#x22;, &#x22;updated&#x22;: &#x22;2022-06-30T14:10:28&#x22;, &#x22;title&#x22;: &#x22;Proba CHRIS Level 1A&#x22;, &#x22;description&#x22;: &#x22;CHRIS acquires a set of up to five images of each target during each acquisition sequence, these images are acquired when Proba-1 is pointing at distinct angles with respect to the target. CHRIS Level 1A products (supplied in HDF data files, version 4.1r3) include five formal CHRIS imaging modes, classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km  All Proba-1 passes are systematically acquired according to the current acquisition plan, CHRIS data are processed every day to Level 1A and made available to ESA users. Observation over a new specific area can be performed by submitting the request to add a new site to the acquisition plan.&#x22;, &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20030920T110000_N51-028_E002-088_0001.SIP.ZIP&#x22;, &#x22;name&#x22;: &#x22;Download&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:DOWNLOAD&#x22;, &#x22;rel&#x22;: &#x22;WWW:DOWNLOAD&#x22;}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20030920T110000_N51-028_E002-088_0001.SIP.ZIP_BID.PNG&#x22;, &#x22;name&#x22;: &#x22;QUICKLOOK&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20030920T110000_N51-028_E002-088_0001.SIP.ZIP_TIMG.jpg&#x22;, &#x22;name&#x22;: &#x22;THUMBNAIL&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.78, 51.22, 2.99, 51.32]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20030920T110000_N51-028_E002-088_0001?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20190401T134300_N51-240_E002-920_0001&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.83, 51.18], [2.83, 51.28], [3.03, 51.28], [3.03, 51.18], [2.83, 51.18]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20190401T134300_N51-240_E002-920_0001&#x22;, &#x22;datetime&#x22;: &#x22;2022-06-30T14:10:17&#x22;, &#x22;start_datetime&#x22;: &#x22;2019-04-01T13:43:00Z&#x22;, &#x22;end_datetime&#x22;: &#x22;2019-04-01T13:47:00Z&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;created&#x22;: &#x22;2019-05-22&#x22;, &#x22;updated&#x22;: &#x22;2022-06-30T14:10:17&#x22;, &#x22;title&#x22;: &#x22;Proba CHRIS Level 1A&#x22;, &#x22;description&#x22;: &#x22;CHRIS acquires a set of up to five images of each target during each acquisition sequence, these images are acquired when Proba-1 is pointing at distinct angles with respect to the target. CHRIS Level 1A products (supplied in HDF data files, version 4.1r3) include five formal CHRIS imaging modes, classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km  All Proba-1 passes are systematically acquired according to the current acquisition plan, CHRIS data are processed every day to Level 1A and made available to ESA users. Observation over a new specific area can be performed by submitting the request to add a new site to the acquisition plan.&#x22;, &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20190401T134300_N51-240_E002-920_0001.SIP.ZIP&#x22;, &#x22;name&#x22;: &#x22;Download&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:DOWNLOAD&#x22;, &#x22;rel&#x22;: &#x22;WWW:DOWNLOAD&#x22;}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20190401T134300_N51-240_E002-920_0001.SIP.ZIP_BID.PNG&#x22;, &#x22;name&#x22;: &#x22;QUICKLOOK&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20190401T134300_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg&#x22;, &#x22;name&#x22;: &#x22;THUMBNAIL&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.83, 51.18, 3.03, 51.28]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20190401T134300_N51-240_E002-920_0001?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.83, 51.18], [2.83, 51.28], [3.02, 51.28], [3.02, 51.18], [2.83, 51.18]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001&#x22;, &#x22;datetime&#x22;: &#x22;2022-06-30T14:16:24&#x22;, &#x22;start_datetime&#x22;: &#x22;2022-03-07T14:02:00Z&#x22;, &#x22;end_datetime&#x22;: &#x22;2022-03-07T14:06:00Z&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;created&#x22;: &#x22;2019-05-22&#x22;, &#x22;updated&#x22;: &#x22;2022-06-30T14:16:24&#x22;, &#x22;title&#x22;: &#x22;Proba CHRIS Level 1A&#x22;, &#x22;description&#x22;: &#x22;CHRIS acquires a set of up to five images of each target during\\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\\n                    classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full\\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022\\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\\n                    distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\\n                    bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half\\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\\n                    Proba-1 passes are systematically acquired according to the current acquisition\\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\\n                    users. Observation over a new specific area can be performed by submitting the\\n                    request to add a new site to the acquisition plan.&#x22;, &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP&#x22;, &#x22;name&#x22;: &#x22;Download&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:DOWNLOAD&#x22;, &#x22;rel&#x22;: &#x22;WWW:DOWNLOAD&#x22;}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG&#x22;, &#x22;name&#x22;: &#x22;QUICKLOOK&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg&#x22;, &#x22;name&#x22;: &#x22;THUMBNAIL&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.83, 51.18, 3.02, 51.28]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;e17fe655-987c-4c5f-bbae-b10dcd4fccc3&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.53, 50.67], [2.53, 51.51], [5.92, 51.51], [5.92, 50.67], [2.53, 50.67]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;e17fe655-987c-4c5f-bbae-b10dcd4fccc3&#x22;, &#x22;datetime&#x22;: &#x22;2022-04-12&#x22;, &#x22;start_datetime&#x22;: &#x22;1997-01-01&#x22;, &#x22;end_datetime&#x22;: &#x22;2020-07-01&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;updated&#x22;: &#x22;2022-04-12&#x22;, &#x22;title&#x22;: &#x22;Biologische Waarderingskaart en Natura 2000 Habitatkaart - Toestand 2020&#x22;, &#x22;description&#x22;: &#x22;De Biologische Waarderingskaart (BWK) is een uniforme inventarisatie en evaluatie van het gehele Vlaamse grondgebied aan de hand van een set karteringseenheden die staan voor vegetaties, bodembedekking en kleine landschapselementen (lijn- en puntvormige elementen). Ook met de aanwezigheid van belangrijke fauna-elementen is er rekening gehouden. De vernieuwde BWK, versie 2, probeert, in vergelijking met de versie 1, aan meer vereisten en noden te voldoen, zowel inhoudelijk als op het gebied van nauwkeurigheid.\\nIn deze versie van de BWK zijn ook de Natura 2000 habitattypen opgenomen. In Vlaanderen komen actueel 47 Natura 2000 habitattypen van de Bijlage I van de Habitatrichtlijn voor. Daarnaast zijn er in Vlaanderen ook 15 regionaal belangrijke biotopen gedefinieerd. Dit zijn biotopen die naar biologische waarden en belang voor de biodiversiteit vergelijkbaar zijn met habitattypen, maar die op Europees niveau minder bedreigd zijn.\\nDeze kaart geeft de best beschikbare informatie anno 2020 over de verspreiding van de Natura 2000 habitattypen, de regionaal belangrijke biotopen en de karteringseenheden van de Biologische Waarderingskaart. Dit kan een vereenvoudiging zijn van de werkelijkheid op terrein. Ten allen tijde geldt de re\\u00eble situatie op terrein voor toepassing t.b.v. het beleidsmatig en wettelijk kader.&#x22;, &#x22;keywords&#x22;: [&#x22;biodiversiteit&#x22;, &#x22;biologische waardering&#x22;, &#x22;biologische waarderingskaart&#x22;, &#x22;biotoop&#x22;, &#x22;biotoopinformatie&#x22;, &#x22;biotoopzeldzaamheid&#x22;, &#x22;diversiteit&#x22;, &#x22;ecotopen&#x22;, &#x22;fauna&#x22;, &#x22;faunistisch belangrijk gebied&#x22;, &#x22;habitat&#x22;, &#x22;habitattype&#x22;, &#x22;landschapselement&#x22;, &#x22;natuurbehoud&#x22;, &#x22;natuurbeleid&#x22;, &#x22;natuurwaarde&#x22;, &#x22;zeldzame diersoorten&#x22;, &#x22;bodembedekking&#x22;, &#x22;bwk&#x22;, &#x22;ecotoop&#x22;, &#x22;flora&#x22;, &#x22;kwetsbaarheid&#x22;, &#x22;landschapselementen&#x22;, &#x22;Natura 2000 habitat&#x22;, &#x22;plantensoorten&#x22;, &#x22;vegetatietypen&#x22;, &#x22;zeldzame soorten&#x22;, &#x22;plantengemeenschap&#x22;, &#x22;habitat 3260&#x22;, &#x22;karteringseenheid&#x22;], &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;http://www.geopunt.be/catalogus/applicationfolder/biologische-waarderingskaart&#x22;, &#x22;name&#x22;: &#x22;Geopunt-applicatie Biologische waarderingskaart&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:LINK-1.0-http--related&#x22;, &#x22;rel&#x22;: &#x22;WWW:LINK-1.0-http--related&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetCapabilities&#x26;version=1.3.0&#x26;service=wms&#x22;, &#x22;name&#x22;: &#x22;BWK2Zone&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Zone&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetMap&#x26;version=1.3.0&#x26;service=wms&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;LAYERS=BWK2Zone&#x26;WIDTH=2048&#x26;HEIGHT=721&#x26;CRS=EPSG:3857&#x26;BBOX=274321.207589895,6600657.3523665415,641218.9433588814,6710879.547153807&#x22;, &#x22;name&#x22;: &#x22;BWK2Zone&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Zone&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetCapabilities&#x26;version=1.3.0&#x26;service=wms&#x22;, &#x22;name&#x22;: &#x22;BWK2Fauna&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Faunistisch belangrijk gebied&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetMap&#x26;version=1.3.0&#x26;service=wms&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;LAYERS=BWK2Fauna&#x26;WIDTH=2048&#x26;HEIGHT=721&#x26;CRS=EPSG:3857&#x26;BBOX=274321.207589895,6600657.3523665415,641218.9433588814,6710879.547153807&#x22;, &#x22;name&#x22;: &#x22;BWK2Fauna&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Faunistisch belangrijk gebied&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetCapabilities&#x26;version=1.3.0&#x26;service=wms&#x22;, &#x22;name&#x22;: &#x22;BWK2Hab&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Natura 2000 Habitat&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetMap&#x26;version=1.3.0&#x26;service=wms&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;LAYERS=BWK2Hab&#x26;WIDTH=2048&#x26;HEIGHT=721&#x26;CRS=EPSG:3857&#x26;BBOX=274321.207589895,6600657.3523665415,641218.9433588814,6710879.547153807&#x22;, &#x22;name&#x22;: &#x22;BWK2Hab&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Natura 2000 Habitat&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetCapabilities&#x26;version=1.3.0&#x26;service=wms&#x22;, &#x22;name&#x22;: &#x22;BWK2Hab3260&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Habitattype 3260&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetMap&#x26;version=1.3.0&#x26;service=wms&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;LAYERS=BWK2Hab3260&#x26;WIDTH=2048&#x26;HEIGHT=721&#x26;CRS=EPSG:3857&#x26;BBOX=274321.207589895,6600657.3523665415,641218.9433588814,6710879.547153807&#x22;, &#x22;name&#x22;: &#x22;BWK2Hab3260&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Habitattype 3260&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetCapabilities&#x26;version=1.3.0&#x26;service=wms&#x22;, &#x22;name&#x22;: &#x22;BWK2ZoneLabel&#x22;, &#x22;description&#x22;: &#x22;Kaartlabel BWK-karteringseenheden&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetMap&#x26;version=1.3.0&#x26;service=wms&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;LAYERS=BWK2ZoneLabel&#x26;WIDTH=2048&#x26;HEIGHT=721&#x26;CRS=EPSG:3857&#x26;BBOX=274321.207589895,6600657.3523665415,641218.9433588814,6710879.547153807&#x22;, &#x22;name&#x22;: &#x22;BWK2ZoneLabel&#x22;, &#x22;description&#x22;: &#x22;Kaartlabel BWK-karteringseenheden&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetCapabilities&#x26;version=1.3.0&#x26;service=wms&#x22;, &#x22;name&#x22;: &#x22;BWK2HabLabel&#x22;, &#x22;description&#x22;: &#x22;Kaartlabel Habitattype&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/inbo/wms?request=GetMap&#x26;version=1.3.0&#x26;service=wms&#x26;FORMAT=image/png&#x26;TRANSPARENT=TRUE&#x26;STYLES=default&#x26;LAYERS=BWK2HabLabel&#x26;WIDTH=2048&#x26;HEIGHT=721&#x26;CRS=EPSG:3857&#x26;BBOX=274321.207589895,6600657.3523665415,641218.9433588814,6710879.547153807&#x22;, &#x22;name&#x22;: &#x22;BWK2HabLabel&#x22;, &#x22;description&#x22;: &#x22;Kaartlabel Habitattype&#x22;, &#x22;type&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS-1.3.0-http-get-map&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/BWK/wfs?service=WFS&#x26;version=1.1.0&#x26;request=GetCapabilities&#x26;typename=BWK:Bwkhab&#x22;, &#x22;name&#x22;: &#x22;BWK:Bwkhab&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - BWK-zone en Natura 2000 Habitat&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-1.1.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-1.1.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/BWK/wfs?service=WFS&#x26;version=1.1.0&#x26;request=GetFeature&#x26;typeName=BWK:Bwkhab&#x26;outputFormat=application/json&#x26;maxFeatures=1&#x26;srsName=epsg:3857&#x22;, &#x22;name&#x22;: &#x22;BWK:Bwkhab&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - BWK-zone en Natura 2000 Habitat&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-1.1.0-http-get-feature&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-1.1.0-http-get-feature&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/BWK/wfs?service=WFS&#x26;version=1.1.0&#x26;request=GetCapabilities&#x26;typename=BWK:Bwkfauna&#x22;, &#x22;name&#x22;: &#x22;BWK:Bwkfauna&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Faunistisch belangrijke gebieden&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-1.1.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-1.1.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/BWK/wfs?service=WFS&#x26;version=1.1.0&#x26;request=GetFeature&#x26;typeName=BWK:Bwkfauna&#x26;outputFormat=application/json&#x26;maxFeatures=1&#x26;srsName=epsg:3857&#x22;, &#x22;name&#x22;: &#x22;BWK:Bwkfauna&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Faunistisch belangrijke gebieden&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-1.1.0-http-get-feature&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-1.1.0-http-get-feature&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/BWK/wfs?service=WFS&#x26;version=1.1.0&#x26;request=GetCapabilities&#x26;typename=BWK:Hab3260&#x22;, &#x22;name&#x22;: &#x22;BWK:Hab3260&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Habitattype 3260&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-1.1.0-http-get-capabilities&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-1.1.0-http-get-capabilities&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/overdrachtdiensten/BWK/wfs?service=WFS&#x26;version=1.1.0&#x26;request=GetFeature&#x26;typeName=BWK:Hab3260&#x26;outputFormat=application/json&#x26;maxFeatures=1&#x26;srsName=epsg:3857&#x22;, &#x22;name&#x22;: &#x22;BWK:Hab3260&#x22;, &#x22;description&#x22;: &#x22;BWK 2 - Habitattype 3260&#x22;, &#x22;type&#x22;: &#x22;OGC:WFS-1.1.0-http-get-feature&#x22;, &#x22;rel&#x22;: &#x22;OGC:WFS-1.1.0-http-get-feature&#x22;}, {&#x22;href&#x22;: &#x22;http://www.geopunt.be/download?container=bwk2\\\\2020&#x26;title=Biologische%20waarderingskaart%20-%20Natura%202000%20Habitatkaart&#x22;, &#x22;name&#x22;: &#x22;Biologische waarderingskaart en Natura 2000 Habitatkaart, uitgave 2020&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:DOWNLOAD-1.0-http--download&#x22;, &#x22;rel&#x22;: &#x22;WWW:DOWNLOAD-1.0-http--download&#x22;}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.53, 50.67, 5.92, 51.51]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/e17fe655-987c-4c5f-bbae-b10dcd4fccc3?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;9d075d6f-a85a-18fa-1f51-ced8-ef7c-5bce-a91eee54&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[2.52, 50.64], [2.52, 51.51], [5.94, 51.51], [5.94, 50.64], [2.52, 50.64]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;9d075d6f-a85a-18fa-1f51-ced8-ef7c-5bce-a91eee54&#x22;, &#x22;datetime&#x22;: &#x22;2022-07-01&#x22;, &#x22;start_datetime&#x22;: null, &#x22;end_datetime&#x22;: null, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;service&#x22;, &#x22;created&#x22;: &#x22;2013-05-27&#x22;, &#x22;updated&#x22;: &#x22;2022-07-01&#x22;, &#x22;title&#x22;: &#x22;WMS Vlaamse Landmaatschappij&#x22;, &#x22;description&#x22;: &#x22;Web Map Service met data van de Vlaamse Landmaatschappij.&#x22;, &#x22;keywords&#x22;: [&#x22;OGC:WMS&#x22;, &#x22;bodemeenheid&#x22;, &#x22;bodemkaart&#x22;, &#x22;gegeneraliseerde bodemkaart voor Vlaanderen&#x22;, &#x22;infiltratiekenmerk&#x22;, &#x22;kwel&#x22;, &#x22;kwetsbaarheid&#x22;, &#x22;landinrichting&#x22;, &#x22;landschapseenheid&#x22;, &#x22;plattelandsbeleid&#x22;, &#x22;reli\\u00ebf&#x22;, &#x22;ruimtelijke structuren in Vlaanderen&#x22;, &#x22;inrichtingsproject&#x22;, &#x22;landinrichtingsplan&#x22;, &#x22;landinrichtingsproject&#x22;, &#x22;onderzoek&#x22;, &#x22;planprogramma&#x22;, &#x22;vastgesteld&#x22;, &#x22;afbakening&#x22;, &#x22;planbegeleidingsgroep&#x22;, &#x22;inrichtingsnota&#x22;, &#x22;recht van voorkoop&#x22;, &#x22;rvv&#x22;, &#x22;voorkoopgebied&#x22;, &#x22;voorkooprecht&#x22;, &#x22;blokgrens&#x22;, &#x22;kavelplan&#x22;, &#x22;landeigendom&#x22;, &#x22;ruilverkaveling&#x22;, &#x22;ruilverkavelingsproject&#x22;, &#x22;sectie&#x22;, &#x22;gebruiksruil&#x22;, &#x22;infrastructuurwerken&#x22;, &#x22;natuurbehoud&#x22;, &#x22;natuurinrichting&#x22;, &#x22;natuurinrichtingsproject&#x22;, &#x22;gebied met recht van voorkoop&#x22;, &#x22;focusgebied&#x22;, &#x22;grondwater&#x22;, &#x22;mestdecreet&#x22;, &#x22;mestactieplan&#x22;, &#x22;nitraat&#x22;, &#x22;nitraatconcentratie&#x22;, &#x22;nitraatresidu&#x22;, &#x22;nitraatresidudrempelwaarde&#x22;, &#x22;nitraatresidustaal&#x22;, &#x22;oppervlaktewater&#x22;, &#x22;overschrijding&#x22;, &#x22;waterkwaliteit&#x22;, &#x22;beheerovereenkomst&#x22;, &#x22;agromilieu-klimaatmaatregel&#x22;, &#x22;ecosysteemdienst&#x22;, &#x22;plattelandsontwikkeling&#x22;, &#x22;landbouwbeleid&#x22;, &#x22;PDPO&#x22;, &#x22;GLB&#x22;, &#x22;agrobiodiveristeit&#x22;, &#x22;gebiedstype&#x22;], &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms?service=WMS&#x26;request=getcapabilities&#x22;, &#x22;name&#x22;: &#x22;Capabilities van de webdienst WMS Vlaamse Landmaatschappij&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;OGC:WMS&#x22;, &#x22;rel&#x22;: &#x22;OGC:WMS&#x22;}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms&#x22;, &#x22;name&#x22;: null, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms&#x22;, &#x22;name&#x22;: null, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}, {&#x22;href&#x22;: &#x22;https://geoservices.informatievlaanderen.be/raadpleegdiensten/VLM/wms&#x22;, &#x22;name&#x22;: null, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[2.52, 50.64, 5.94, 51.51]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/9d075d6f-a85a-18fa-1f51-ced8-ef7c-5bce-a91eee54?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}, {&#x22;id&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001&#x22;, &#x22;type&#x22;: &#x22;Feature&#x22;, &#x22;geometry&#x22;: {&#x22;type&#x22;: &#x22;Polygon&#x22;, &#x22;coordinates&#x22;: [[[3.07, 51.29], [3.07, 51.39], [3.28, 51.39], [3.28, 51.29], [3.07, 51.29]]]}, &#x22;properties&#x22;: {&#x22;externalId&#x22;: &#x22;PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001&#x22;, &#x22;datetime&#x22;: &#x22;2022-06-30T14:09:50&#x22;, &#x22;start_datetime&#x22;: &#x22;2018-10-05T13:46:00Z&#x22;, &#x22;end_datetime&#x22;: &#x22;2018-10-05T13:50:00Z&#x22;, &#x22;recordUpdated&#x22;: &#x22;2022-07-21T22:40:13Z&#x22;, &#x22;type&#x22;: &#x22;dataset&#x22;, &#x22;created&#x22;: &#x22;2019-05-22&#x22;, &#x22;updated&#x22;: &#x22;2022-06-30T14:09:50&#x22;, &#x22;title&#x22;: &#x22;Proba CHRIS Level 1A&#x22;, &#x22;description&#x22;: &#x22;CHRIS acquires a set of up to five images of each target during each acquisition sequence, these images are acquired when Proba-1 is pointing at distinct angles with respect to the target. CHRIS Level 1A products (supplied in HDF data files, version 4.1r3) include five formal CHRIS imaging modes, classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km  All Proba-1 passes are systematically acquired according to the current acquisition plan, CHRIS data are processed every day to Level 1A and made available to ESA users. Observation over a new specific area can be performed by submitting the request to add a new site to the acquisition plan.&#x22;, &#x22;associations&#x22;: [{&#x22;href&#x22;: &#x22;https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001.SIP.ZIP&#x22;, &#x22;name&#x22;: &#x22;Download&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: &#x22;WWW:DOWNLOAD&#x22;, &#x22;rel&#x22;: &#x22;WWW:DOWNLOAD&#x22;}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001.SIP.ZIP_BID.PNG&#x22;, &#x22;name&#x22;: &#x22;QUICKLOOK&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}, {&#x22;href&#x22;: &#x22;http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001.SIP.ZIP_TIMG.jpg&#x22;, &#x22;name&#x22;: &#x22;THUMBNAIL&#x22;, &#x22;description&#x22;: null, &#x22;type&#x22;: null, &#x22;rel&#x22;: null}], &#x22;extent&#x22;: {&#x22;spatial&#x22;: {&#x22;bbox&#x22;: [[3.07, 51.29, 3.28, 51.39]], &#x22;crs&#x22;: &#x22;http://www.opengis.net/def/crs/OGC/1.3/CRS84&#x22;}}}, &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;via&#x22;, &#x22;type&#x22;: &#x22;application/xml&#x22;, &#x22;title&#x22;: &#x22;This document as XML&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?f=xml&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}], &#x22;assets&#x22;: {}}], &#x22;links&#x22;: [{&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/dcs+geo&#x22;, &#x22;title&#x22;: &#x22;This document as DCS + GeoJSON&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?f=dcs+geo&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}, {&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/jose&#x22;, &#x22;title&#x22;: &#x22;This document as JOSE + GeoJSON&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?f=jose&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}, {&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/jose;profile=jws", "title": "This document as JWS", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?f=jws", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/geo+json", "title": "This document as GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?f=json", "hreflang": "en-US"}, {"rel": "alternate", "type": "text/html", "title": "This document as HTML", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20181005T134600_N51-350_E003-170_0001?f=html", "hreflang": "en-US"}, {"rel": "collection", "type": "application/json", "title": "Collection URL", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main", "hreflang": "en-US"}], "numberMatched": 39, "numberReturned": 10, "bbox": [-180.0, -90.0, 180.0, 90.0]}'

Figure A.11

A.2.3.  D113 GET /items/{itemId} without DCS (GeoJSON)

Example: 1.3
> Access the OGC API-Records D113 /items/{itemId} without DCS (GeoJSON)

response = requests.get(endpoint_item ,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/geo+json'})

data = json.loads(response.text)
jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

Figure A.12

{
  
"id": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001",
  
"type": "Feature",
  
"geometry": {
     
"type": "Polygon",
     
"coordinates": [
        
[
           
[
              
2.83,
              
51.18
           
],
           
[
              
2.83,
              
51.28
           
],
           
[
              
3.02,
              
51.28
           
],
           
[
              
3.02,
              
51.18
           
],
           
[
              
2.83,
              
51.18
           
]
        
]
     
]
  
},
  
"properties": {
     
"externalId": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001",
     
"datetime": "2022-06-30T14:16:24",
     
"start_datetime": "2022-03-07T14:02:00Z",
     
"end_datetime": "2022-03-07T14:06:00Z",
     
"recordUpdated": "2022-07-21T22:40:13Z",
     
"type": "dataset",
     
"created": "2019-05-22",
     
"updated": "2022-06-30T14:16:24",
     
"title": "Proba CHRIS Level 1A",
     
"description": "CHRIS acquires a set of up to five images of each target during\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\n                    classified as modes 1 to 5: \u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \u2022 MODE 2 WATER BANDS: Full\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \u2022\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\n                    distance 17m @ 556km \u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\n                    bands, nadir ground sampling distance 17m @ 556km \u2022 MODE 5 LAND CHANNELS: Half\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\n                    Proba-1 passes are systematically acquired according to the current acquisition\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\n                    users. Observation over a new specific area can be performed by submitting the\n                    request to add a new site to the acquisition plan.",
     
"associations": [
        
{
           
"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP",
           
"name": "Download",
           
"description": null,
           
"type": "WWW:DOWNLOAD",
           
"rel": "WWW:DOWNLOAD"
        
},
        
{
           
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG",
           
"name": "QUICKLOOK",
           
"description": null,
           
"type": null,
           
"rel": null
        
},
        
{
           
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg",
           
"name": "THUMBNAIL",
           
"description": null,
           
"type": null,
           
"rel": null
        
}
     
],
     
"extent": {
        
"spatial": {
           
"bbox": [
              
[
                 
2.83,
                 
51.18,
                 
3.02,
                 
51.28
              
]
           
],
           
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
        
}
     
}
  
},
  
"links": [
     
{
        
"rel": "alternate",
        
"type": "application/dcs+geo",
        
"title": "This document as DCS + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=dcs+geo",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose",
        
"title": "This document as JOSE + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jose",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose;profile=jws",
        
"title": "This document as JWS",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jws",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "self",
        
"type": "application/geo+json",
        
"title": "This document as GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=json",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "text/html",
        
"title": "This document as HTML",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=html",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "collection",
        
"type": "application/json",
        
"title": "Collection URL",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "via",
        
"type": "application/xml",
        
"title": "This document as XML",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=xml",
        
"hreflang": "en-US"
     
}
  
],
  
"assets": {}
}

Figure A.13

The ISO metadata record is available via the via link at JSONPath $.links[?(@.rel==`via’)].

from jsonpath_ng.ext import parse

expression = parse("$.links[?(@.rel == 'via')].href")
r = expression.find(data)
r[0].value

Figure A.14

'https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=xml'

Figure A.15

show_on_map(data)

Figure A.16

Make this Notebook Trusted to load map: File → Trust Notebook

A.2.4.  D113 GET /queryables without DCS (JSON)

Example: 1.4
> Access the OGC API-Records D113 /collections/{collection-id}/queryables without DCS to retrieve the available search parameters.

response = requests.get(endpoint_queryables ,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json'})

data = json.loads(response.text)
jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

Figure A.17

{
  
"id": "metadata:main",
  
"type": "object",
  
"title": "OGC Testbed 18 Geospatial Catalogue",
  
"properties": {
     
"geometry": {
        
"$ref": "https://geojson.org/schema/Polygon.json"
     
},
     
"type": {
        
"title": "type",
        
"type": "string"
     
},
     
"title": {
        
"title": "title",
        
"type": "string"
     
},
     
"keywords": {
        
"title": "keywords",
        
"type": "string"
     
},
     
"parentidentifier": {
        
"title": "parentidentifier",
        
"type": "string"
     
},
     
"time_begin": {
        
"title": "time_begin",
        
"type": "string"
     
},
     
"time_end": {
        
"title": "time_end",
        
"type": "string"
     
},
     
"date": {
        
"title": "date",
        
"type": "string"
     
},
     
"platform": {
        
"title": "platform",
        
"type": "string"
     
},
     
"instrument": {
        
"title": "instrument",
        
"type": "string"
     
},
     
"sensortype": {
        
"title": "sensortype",
        
"type": "string"
     
}
  
},
  
"$schema": "http://json-schema.org/draft/2019-09/schema",
  
"$id": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/queryables"
}

Figure A.18

A.2.5.  D113 GET /items/{itemId} without DCS (XML)

Example: 1.5
> Access the OGC API-Records D113 /items/{itemId} without DCS (XML) to retrieve an ISO19139 metadata record.

response = requests.get(endpoint_item + '?f=xml',
    verify=bool(verify_ssl),
    headers={})
# headers={'Accept': 'application/xml'})

xmlstr = minidom.parseString(response.text).toprettyxml(indent='  ',newl='')
md("```xml\n" + xmlstr + "\n```\n")

Figure A.19

<?xml version="1.0" ?><gmd:MD_Metadata xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:gmx="http://www.isotc211.org/2005/gmx" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.isotc211.org/2005/gmd ./apiso-inspire.xsd">
      <gmd:fileIdentifier>
            <gco:CharacterString>PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001</gco:CharacterString>
      </gmd:fileIdentifier>
      <gmd:language>
            <gmd:LanguageCode codeList="http://id.loc.gov/vocabulary/iso639-2" codeListValue="eng">eng</gmd:LanguageCode>
      </gmd:language>
      <gmd:parentIdentifier>
            <gmx:Anchor xlink:href="https://eovoc.spacebel.be/collections/series/items/PROBA.CHRIS.1A">PROBA.CHRIS.1A</gmx:Anchor>
      </gmd:parentIdentifier>
      <gmd:hierarchyLevel>
            <gmd:MD_ScopeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#MD_ScopeCode" codeListValue="dataset"/>
      </gmd:hierarchyLevel>
      <gmd:contact xmlns:gmd="http://www.isotc211.org/2005/gmd">
            <gmd:CI_ResponsibleParty>
                  <gmd:organisationName>
                        <gco:CharacterString>ESA/ESRIN</gco:CharacterString>
                  </gmd:organisationName>
                  <gmd:positionName>
                        <gco:CharacterString>ESRIN Earth Observation Help Desk</gco:CharacterString>
                  </gmd:positionName>
                  <gmd:contactInfo>
                        <gmd:CI_Contact>
                              <gmd:phone>
                                    <gmd:CI_Telephone>
                                          <gmd:voice>
                                                <gco:CharacterString>+3906941801</gco:CharacterString>
                                          </gmd:voice>
                                          <gmd:facsimile>
                                                <gco:CharacterString>+390694180280</gco:CharacterString>
                                          </gmd:facsimile>
                                    </gmd:CI_Telephone>
                              </gmd:phone>
                              <gmd:address>
                                    <gmd:CI_Address>
                                          <gmd:deliveryPoint>
                                                <gco:CharacterString>Largo Galileo Galilei 1</gco:CharacterString>
                                          </gmd:deliveryPoint>
                                          <gmd:city>
                                                <gco:CharacterString>Frascati (Roma)</gco:CharacterString>
                                          </gmd:city>
                                          <gmd:postalCode>
                                                <gco:CharacterString>00044</gco:CharacterString>
                                          </gmd:postalCode>
                                          <gmd:country>
                                                <gco:CharacterString>Italy</gco:CharacterString>
                                          </gmd:country>
                                          <gmd:electronicMailAddress>
                                                <gco:CharacterString>eohelp@esa.int</gco:CharacterString>
                                          </gmd:electronicMailAddress>
                                    </gmd:CI_Address>
                              </gmd:address>
                              <gmd:onlineResource>
                                    <gmd:CI_OnlineResource>
                                          <gmd:linkage>
                                                <gmd:URL>http://www.esa.int</gmd:URL>
                                          </gmd:linkage>
                                    </gmd:CI_OnlineResource>
                              </gmd:onlineResource>
                        </gmd:CI_Contact>
                  </gmd:contactInfo>
                  <role xmlns="http://www.isotc211.org/2005/gmd">
                        <gmd:CI_RoleCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
                  </role>
            </gmd:CI_ResponsibleParty>
      </gmd:contact>
      <gmd:dateStamp>
            <gco:DateTime>2022-06-30T14:16:24</gco:DateTime>
      </gmd:dateStamp>
      <gmd:metadataStandardName>
            <gco:CharacterString>ISO19115</gco:CharacterString>
      </gmd:metadataStandardName>
      <gmd:metadataStandardVersion>
            <gco:CharacterString>2005/Cor.1:2006</gco:CharacterString>
      </gmd:metadataStandardVersion>
      <gmd:referenceSystemInfo>
            <gmd:MD_ReferenceSystem>
                  <gmd:referenceSystemIdentifier>
                        <gmd:RS_Identifier>
                              <gmd:code>
                                    <gmx:Anchor xlink:href="http://www.opengis.net/def/crs/EPSG/0/4326">EPSG:4326</gmx:Anchor>
                              </gmd:code>
                        </gmd:RS_Identifier>
                  </gmd:referenceSystemIdentifier>
            </gmd:MD_ReferenceSystem>
      </gmd:referenceSystemInfo>
      <gmd:identificationInfo>
            <gmd:MD_DataIdentification>
                  <gmd:citation>
                        <gmd:CI_Citation>
                              <gmd:title>
                                    <gco:CharacterString>Proba CHRIS Level 1A</gco:CharacterString>
                              </gmd:title>
                              <gmd:date>
                                    <gmd:CI_Date>
                                          <!-- Metadata Identification Creation Date  (MI_CD)-->
                                          <gmd:date>
                                                <gco:Date>2019-05-22</gco:Date>
                                          </gmd:date>
                                          <gmd:dateType>
                                                <gmd:CI_DateTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="creation"/>
                                          </gmd:dateType>
                                    </gmd:CI_Date>
                              </gmd:date>
                              <gmd:identifier>
                                    <gmd:MD_Identifier>
                                          <gmd:code>
                                                <gmx:Anchor xlink:href="https://eovoc.spacebel.be/collections/datasets/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001"/>
                                          </gmd:code>
                                    </gmd:MD_Identifier>
                              </gmd:identifier>
                        </gmd:CI_Citation>
                  </gmd:citation>
                  <gmd:abstract>
                        <gco:CharacterString>CHRIS acquires a set of up to five images of each target during
                    each acquisition sequence, these images are acquired when Proba-1 is pointing at
                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in
                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,
                    classified as modes 1 to 5: • MODE 1: Full swath width, 62 spectral bands, 773nm
                    / 1036nm, nadir ground sampling distance 34m @ 556km • MODE 2 WATER BANDS: Full
                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km •
                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling
                    distance 17m @ 556km • MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral
                    bands, nadir ground sampling distance 17m @ 556km • MODE 5 LAND CHANNELS: Half
                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All
                    Proba-1 passes are systematically acquired according to the current acquisition
                    plan, CHRIS data are processed every day to Level 1A and made available to ESA
                    users. Observation over a new specific area can be performed by submitting the
                    request to add a new site to the acquisition plan.</gco:CharacterString>
                  </gmd:abstract>
                  <gmd:pointOfContact>
                        <gmd:CI_ResponsibleParty>
                              <gmd:organisationName>
                                    <gco:CharacterString>ESA/ESRIN</gco:CharacterString>
                              </gmd:organisationName>
                              <gmd:positionName>
                                    <gco:CharacterString>Earth Observation helpdesk</gco:CharacterString>
                              </gmd:positionName>
                              <gmd:contactInfo>
                                    <gmd:CI_Contact>
                                          <gmd:phone>
                                                <gmd:CI_Telephone>
                                                      <gmd:voice>
                                                            <gco:CharacterString>+3906941801</gco:CharacterString>
                                                      </gmd:voice>
                                                      <gmd:facsimile>
                                                            <gco:CharacterString>+390694180280</gco:CharacterString>
                                                      </gmd:facsimile>
                                                </gmd:CI_Telephone>
                                          </gmd:phone>
                                          <gmd:address>
                                                <gmd:CI_Address>
                                                      <gmd:deliveryPoint>
                                                            <gco:CharacterString>Largo Galileo Galilei
                                            1</gco:CharacterString>
                                                      </gmd:deliveryPoint>
                                                      <gmd:city>
                                                            <gco:CharacterString>Frascati (Roma)</gco:CharacterString>
                                                      </gmd:city>
                                                      <gmd:postalCode>
                                                            <gco:CharacterString>00044</gco:CharacterString>
                                                      </gmd:postalCode>
                                                      <gmd:country>
                                                            <gco:CharacterString>Italy</gco:CharacterString>
                                                      </gmd:country>
                                                      <gmd:electronicMailAddress>
                                                            <gco:CharacterString>eohelp@esa.int</gco:CharacterString>
                                                      </gmd:electronicMailAddress>
                                                </gmd:CI_Address>
                                          </gmd:address>
                                          <gmd:onlineResource>
                                                <gmd:CI_OnlineResource>
                                                      <gmd:linkage>
                                                            <gmd:URL>http://www.esa.int</gmd:URL>
                                                      </gmd:linkage>
                                                </gmd:CI_OnlineResource>
                                          </gmd:onlineResource>
                                    </gmd:CI_Contact>
                              </gmd:contactInfo>
                              <gmd:role>
                                    <gmd:CI_RoleCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="originator">originator</gmd:CI_RoleCode>
                              </gmd:role>
                        </gmd:CI_ResponsibleParty>
                  </gmd:pointOfContact>
                  <gmd:graphicOverview>
                        <gmd:MD_BrowseGraphic>
                              <gmd:fileName>
                                    <gco:CharacterString>http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG</gco:CharacterString>
                              </gmd:fileName>
                        </gmd:MD_BrowseGraphic>
                  </gmd:graphicOverview>
                  <gmd:descriptiveKeywords>
                        <gmd:MD_Keywords>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/theme/lc">Land
                            cover</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:thesaurusName>
                                    <gmd:CI_Citation>
                                          <gmd:title>
                                                <gmx:Anchor xlink:href="http://www.eionet.europa.eu/gemet/inspire_themes">GEMET - INSPIRE themes, version 1.0</gmx:Anchor>
                                          </gmd:title>
                                          <gmd:date>
                                                <gmd:CI_Date>
                                                      <gmd:date>
                                                            <gco:Date>2008-06-01</gco:Date>
                                                      </gmd:date>
                                                      <gmd:dateType>
                                                            <gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>
                                                      </gmd:dateType>
                                                </gmd:CI_Date>
                                          </gmd:date>
                                    </gmd:CI_Citation>
                              </gmd:thesaurusName>
                        </gmd:MD_Keywords>
                  </gmd:descriptiveKeywords>
                  <gmd:descriptiveKeywords>
                        <gmd:MD_Keywords>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://gcmd.earthdata.nasa.gov/kms/concept/46e4aaa4-349c-4049-a910-035391360010">EARTH SCIENCE &#x3e; BIOSPHERE &#x3e; ECOSYSTEMS &#x3e; TERRESTRIAL
                            ECOSYSTEMS</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://gcmd.earthdata.nasa.gov/kms/concept/c7b5c02c-724d-4a19-b824-98180f3900c9">EARTH SCIENCE &#x3e; BIOSPHERE &#x3e; VEGETATION</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://gcmd.earthdata.nasa.gov/kms/concept/5debb283-51e4-435e-b2a2-e8e2a977220d">EARTH SCIENCE &#x3e; TERRESTRIAL HYDROSPHERE &#x3e; SURFACE
                            WATER</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://gcmd.earthdata.nasa.gov/kms/concept/91697b7d-8f2b-4954-850e-61d5f61c867d">EARTH SCIENCE &#x3e; OCEANS</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:type>
                                    <gmd:MD_KeywordTypeCode codeList="theme" codeListValue="http://www.isotc211.org/2005/resources/codeList.xml#MD_KeywordTypeCode"/>
                              </gmd:type>
                              <gmd:thesaurusName>
                                    <gmd:CI_Citation>
                                          <gmd:title>
                                                <gmx:Anchor xlink:href="https://gcmd.earthdata.nasa.gov/kms/concepts/concept_scheme/sciencekeywords">NASA/Global Change Master Directory (GCMD) Earth Science
                                    Keywords. Version 8.6</gmx:Anchor>
                                          </gmd:title>
                                          <gmd:date>
                                                <gmd:CI_Date>
                                                      <gmd:date>
                                                            <gco:Date>2018</gco:Date>
                                                      </gmd:date>
                                                      <gmd:dateType>
                                                            <gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>
                                                      </gmd:dateType>
                                                </gmd:CI_Date>
                                          </gmd:date>
                                          <gmd:identifier>
                                                <gmd:MD_Identifier>
                                                      <gmd:code>
                                                            <gco:CharacterString>http://idn.ceos.org/</gco:CharacterString>
                                                      </gmd:code>
                                                </gmd:MD_Identifier>
                                          </gmd:identifier>
                                    </gmd:CI_Citation>
                              </gmd:thesaurusName>
                        </gmd:MD_Keywords>
                  </gmd:descriptiveKeywords>
                  <gmd:descriptiveKeywords>
                        <gmd:MD_Keywords>
                              <!--                                                (K_ET_U)     (K_ET)   -->
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://earth.esa.int/concept/forestry">Forestry</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://earth.esa.int/concept/vegetation">Vegetation</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://earth.esa.int/concept/surface-water">Surface
                            Water</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://earth.esa.int/concept/oceans">Oceans</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:thesaurusName>
                                    <gmd:CI_Citation>
                                          <gmd:title>
                                                <gmx:Anchor xlink:href="https://earth.esa.int/concepts/concept_scheme/earth-topics">EO Parameter Code List - Earth Topics</gmx:Anchor>
                                          </gmd:title>
                                          <gmd:date>
                                                <gmd:CI_Date>
                                                      <gmd:date>
                                                            <gco:Date>2018</gco:Date>
                                                      </gmd:date>
                                                      <gmd:dateType>
                                                            <gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>
                                                      </gmd:dateType>
                                                </gmd:CI_Date>
                                          </gmd:date>
                                    </gmd:CI_Citation>
                              </gmd:thesaurusName>
                        </gmd:MD_Keywords>
                  </gmd:descriptiveKeywords>
                  <gmd:descriptiveKeywords>
                        <gmd:MD_Keywords>
                              <!--                                                (I_E_T_U)              (I_E_T)   -->
                              <gmd:keyword>
                                    <gmx:Anchor xlink:href="https://earth.esa.int/concept/p-imaging-spectrometers-radiometers">Imaging Spectrometers/Radiometers</gmx:Anchor>
                              </gmd:keyword>
                              <gmd:type>
                                    <gmd:MD_KeywordTypeCode codeList="http://www.isotc211.org/2005/resources/codeList.xml#MD_KeywordTypeCode" codeListValue="theme"/>
                              </gmd:type>
                              <gmd:thesaurusName>
                                    <gmd:CI_Citation>
                                          <gmd:title>
                                                <gmx:Anchor xlink:href="https://earth.esa.int/concepts/concept_scheme/instruments">EO Parameter Code List - Instruments</gmx:Anchor>
                                          </gmd:title>
                                          <gmd:date>
                                                <gmd:CI_Date>
                                                      <gmd:date>
                                                            <gco:Date>2018</gco:Date>
                                                      </gmd:date>
                                                      <gmd:dateType>
                                                            <gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>
                                                      </gmd:dateType>
                                                </gmd:CI_Date>
                                          </gmd:date>
                                    </gmd:CI_Citation>
                              </gmd:thesaurusName>
                        </gmd:MD_Keywords>
                  </gmd:descriptiveKeywords>
                  <gmd:resourceConstraints>
                        <gmd:MD_LegalConstraints>
                              <gmd:accessConstraints>
                                    <gmd:MD_RestrictionCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_RestrictionCode" codeListValue="otherRestrictions"/>
                              </gmd:accessConstraints>
                              <gmd:otherConstraints>
                                    <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/metadata-codelist/LimitationsOnPublicAccess/noLimitations"/>
                              </gmd:otherConstraints>
                        </gmd:MD_LegalConstraints>
                  </gmd:resourceConstraints>
                  <gmd:resourceConstraints>
                        <gmd:MD_LegalConstraints>
                              <gmd:accessConstraints>
                                    <gmd:MD_RestrictionCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_RestrictionCode" codeListValue="otherRestrictions"/>
                              </gmd:accessConstraints>
                              <gmd:otherConstraints>
                                    <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/metadata-codelist/ConditionsApplyingToAccessAndUse/conditionsUnknown"/>
                              </gmd:otherConstraints>
                              <gmd:otherConstraints>
                                    <gmx:Anchor xlink:href="https://earth.esa.int/eogateway/documents/20142/1560778/ESA-Third-Party-Missions-Terms-and-Conditions.pdf">Utilisation of this data is subject to ESA's Earth Observation Terms
                            and Conditions </gmx:Anchor>
                              </gmd:otherConstraints>
                        </gmd:MD_LegalConstraints>
                  </gmd:resourceConstraints>
                  <gmd:spatialRepresentationType>
                        <gmd:MD_SpatialRepresentationTypeCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_SpatialRepresentationTypeCode" codeListValue="grid"/>
                  </gmd:spatialRepresentationType>
                  <gmd:language>
                        <gmd:LanguageCode codeList="http://id.loc.gov/vocabulary/iso639-2" codeListValue="eng">eng</gmd:LanguageCode>
                  </gmd:language>
                  <gmd:topicCategory>
                        <gmd:MD_TopicCategoryCode>imageryBaseMapsEarthCover</gmd:MD_TopicCategoryCode>
                  </gmd:topicCategory>
                  <gmd:extent>
                        <gmd:EX_Extent>
                              <gmd:temporalElement>
                                    <gmd:EX_TemporalExtent>
                                          <gmd:extent>
                                                <gml:TimePeriod gml:id="timeperiod1">
                                                      <gml:beginPosition>2022-03-07T14:02:00Z</gml:beginPosition>
                                                      <gml:endPosition>2022-03-07T14:06:00Z</gml:endPosition>
                                                </gml:TimePeriod>
                                          </gmd:extent>
                                    </gmd:EX_TemporalExtent>
                              </gmd:temporalElement>
                        </gmd:EX_Extent>
                  </gmd:extent>
                  <gmd:extent>
                        <gmd:EX_Extent>
                              <gmd:geographicElement>
                                    <gmd:EX_GeographicBoundingBox>
                                          <gmd:westBoundLongitude>
                                                <gco:Decimal>2.83</gco:Decimal>
                                          </gmd:westBoundLongitude>
                                          <gmd:eastBoundLongitude>
                                                <gco:Decimal>3.02</gco:Decimal>
                                          </gmd:eastBoundLongitude>
                                          <gmd:southBoundLatitude>
                                                <gco:Decimal>51.18</gco:Decimal>
                                          </gmd:southBoundLatitude>
                                          <gmd:northBoundLatitude>
                                                <gco:Decimal>51.28</gco:Decimal>
                                          </gmd:northBoundLatitude>
                                    </gmd:EX_GeographicBoundingBox>
                              </gmd:geographicElement>
                        </gmd:EX_Extent>
                  </gmd:extent>
            </gmd:MD_DataIdentification>
      </gmd:identificationInfo>
      <gmd:distributionInfo>
            <gmd:MD_Distribution>
                  <gmd:distributionFormat>
                        <gmd:MD_Format>
                              <gmd:name>
                                    <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/media-types/application/x-binary">application/x-binary</gmx:Anchor>
                              </gmd:name>
                              <gmd:version gco:nilReason="unknown"/>
                        </gmd:MD_Format>
                  </gmd:distributionFormat>
                  <gmd:transferOptions>
                        <gmd:MD_DigitalTransferOptions>
                              <gmd:onLine>
                                    <gmd:CI_OnlineResource>
                                          <gmd:linkage>
                                                <gmd:URL>https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP</gmd:URL>
                                          </gmd:linkage>
                                          <gmd:protocol>
                                                <gmx:Anchor xlink:href="https://www.iana.org/assignments/media-types/application/x-binary">application/x-binary</gmx:Anchor>
                                          </gmd:protocol>
                                          <gmd:applicationProfile>
                                                <gco:CharacterString>application/x-binary</gco:CharacterString>
                                          </gmd:applicationProfile>
                                          <gmd:name>
                                                <gco:CharacterString>Download</gco:CharacterString>
                                          </gmd:name>
                                          <gmd:description>
                                                <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/metadata-codelist/OnLineDescriptionCode/endPoint">endPoint</gmx:Anchor>
                                          </gmd:description>
                                          <gmd:function>
                                                <gmd:CI_OnLineFunctionCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="information"/>
                                          </gmd:function>
                                    </gmd:CI_OnlineResource>
                              </gmd:onLine>
                              <gmd:onLine>
                                    <gmd:CI_OnlineResource>
                                          <gmd:linkage>
                                                <gmd:URL>http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG</gmd:URL>
                                          </gmd:linkage>
                                          <gmd:protocol>
                                                <gmx:Anchor xlink:href="https://www.iana.org/assignments/media-types/image/png">png</gmx:Anchor>
                                          </gmd:protocol>
                                          <gmd:applicationProfile>
                                                <gco:CharacterString>image/png</gco:CharacterString>
                                          </gmd:applicationProfile>
                                          <gmd:name>
                                                <gco:CharacterString>QUICKLOOK</gco:CharacterString>
                                          </gmd:name>
                                          <gmd:description>
                                                <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/metadata-codelist/OnLineDescriptionCode/endPoint">endPoint</gmx:Anchor>
                                          </gmd:description>
                                          <gmd:function>
                                                <gmd:CI_OnLineFunctionCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="information"/>
                                          </gmd:function>
                                    </gmd:CI_OnlineResource>
                              </gmd:onLine>
                              <gmd:onLine>
                                    <gmd:CI_OnlineResource>
                                          <gmd:linkage>
                                                <gmd:URL>http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg</gmd:URL>
                                          </gmd:linkage>
                                          <gmd:protocol>
                                                <gmx:Anchor xlink:href="https://www.iana.org/assignments/media-types/image/jpeg">jpeg</gmx:Anchor>
                                          </gmd:protocol>
                                          <gmd:applicationProfile>
                                                <gco:CharacterString>image/jpeg</gco:CharacterString>
                                          </gmd:applicationProfile>
                                          <gmd:name>
                                                <gco:CharacterString>THUMBNAIL</gco:CharacterString>
                                          </gmd:name>
                                          <gmd:description>
                                                <gmx:Anchor xlink:href="http://inspire.ec.europa.eu/metadata-codelist/OnLineDescriptionCode/endPoint">endPoint</gmx:Anchor>
                                          </gmd:description>
                                          <gmd:function>
                                                <gmd:CI_OnLineFunctionCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="information"/>
                                          </gmd:function>
                                    </gmd:CI_OnlineResource>
                              </gmd:onLine>
                        </gmd:MD_DigitalTransferOptions>
                  </gmd:transferOptions>
            </gmd:MD_Distribution>
      </gmd:distributionInfo>
      <gmd:dataQualityInfo>
            <gmd:DQ_DataQuality>
                  <gmd:scope>
                        <gmd:DQ_Scope>
                              <gmd:level>
                                    <gmd:MD_ScopeCode codeList="http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#MD_ScopeCode" codeListValue="dataset"/>
                              </gmd:level>
                              <gmd:levelDescription>
                                    <gmd:MD_ScopeDescription>
                                          <gmd:other>
                                                <gco:CharacterString>Dataset</gco:CharacterString>
                                          </gmd:other>
                                    </gmd:MD_ScopeDescription>
                              </gmd:levelDescription>
                        </gmd:DQ_Scope>
                  </gmd:scope>
                  <gmd:report>
                        <gmd:DQ_DomainConsistency>
                              <gmd:result>
                                    <gmd:DQ_ConformanceResult>
                                          <gmd:specification>
                                                <gmd:CI_Citation>
                                                      <gmd:title>
                                                            <gmx:Anchor xlink:href="http://data.europa.eu/eli/reg/2010/1089">COMMISSION REGULATION (EU) No 1089/2010 of 23 November
                                            2010 implementing Directive 2007/2/EC of the European
                                            Parliament and of the Council as regards
                                            interoperability of spatial data sets and
                                            services</gmx:Anchor>
                                                      </gmd:title>
                                                      <gmd:date>
                                                            <gmd:CI_Date>
                                                                  <gmd:date>
                                                                        <gco:Date>2010-12-08</gco:Date>
                                                                  </gmd:date>
                                                                  <gmd:dateType>
                                                                        <gmd:CI_DateTypeCode codeList="http://standards.iso.org/ittf/PubliclyAvailableStandards/ISO_19139_Schemas/resources/codelist/ML_gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>
                                                                  </gmd:dateType>
                                                            </gmd:CI_Date>
                                                      </gmd:date>
                                                </gmd:CI_Citation>
                                          </gmd:specification>
                                          <gmd:explanation>
                                                <gco:CharacterString>This data set is conformant with the INSPIRE
                                    Implementing Rules for the interoperability of spatial data sets
                                    and services</gco:CharacterString>
                                          </gmd:explanation>
                                          <gmd:pass>
                                                <gco:Boolean>false</gco:Boolean>
                                          </gmd:pass>
                                    </gmd:DQ_ConformanceResult>
                              </gmd:result>
                        </gmd:DQ_DomainConsistency>
                  </gmd:report>
                  <gmd:lineage>
                        <gmd:LI_Lineage>
                              <gmd:statement>
                                    <gco:CharacterString>source data: PROBA platform</gco:CharacterString>
                              </gmd:statement>
                        </gmd:LI_Lineage>
                  </gmd:lineage>
            </gmd:DQ_DataQuality>
      </gmd:dataQualityInfo>
</gmd:MD_Metadata>

Figure A.20

A.3.  D113 GET /items with DCS (KMS)

Example: 2.1
> Access the OGC API-Records D113 /items with DCS (application/dcs+geo)

# Get the access token from https://ogc.demo.secure-dimensions.de/token-app/
# access_token = '4572e42da2c093012606449ba29da41fad2d599b'

# response = requests.get(endpoint_items + '?key_challenge=123&limit=1&access_token='+access_token,
response = requests.get(endpoint_items + '?key_challenge=123&limit=1&type=series',
    verify=bool(verify_ssl),
    headers={'Accept': 'application/dcs+geo', 'Authorization':  'Bearer ' + access_token})

response

Figure A.21

<Response [200]>

Figure A.22

A.3.1.  JWT

Catalogue response corresponds to a JWT. The complete response is a JWE. The syntax is defined at https://openid.net/specs/draft-jones-json-web-encryption-02.html Contains 3 parts separated by dots…

token = response.text
token

Figure A.23

'{"type": "dcs+geo", "timestamp": "2022-10-21T17:25:39+02:00", "objects": [{"metadata": {"confidentiality_information": {"policy_identifier": "TB18", "classification": "unclassified"}, "creation_data_time": "2022-10-21T17:25:39+02:00", "number_matched": 4, "number_returned": 1, "bbox": [], "links": [{"rel": "self", "type": "application/dcs+geo", "title": "This document as DCS + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&#x26;limit=1&#x26;type=series&#x26;f=dcs+geo&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}, {&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/jose&#x22;, &#x22;title&#x22;: &#x22;This document as JOSE + GeoJSON&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&#x26;limit=1&#x26;type=series&#x26;f=jose&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}, {&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/jose;profile=jws", "title": "This document as JWS", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&limit=1&type=series&f=jws", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/geo+json", "title": "This document as GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99?f=json", "hreflang": "en-US"}, {"rel": "alternate", "type": "text/html", "title": "This document as HTML", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99?f=html", "hreflang": "en-US"}, {"rel": "collection", "type": "application/json", "title": "Collection URL", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main", "hreflang": "en-US"}, {"rel": "next", "type": "application/dcs+geo", "title": "items (next)", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&limit=1&type=series&f=dcs+geo&offset=1", "hreflang": "en-US"}]}, "data": "eyJhbGciOiJkaXIiLCJjcml0IjpbImt1cmwiXSwiY3R5IjoiYXBwbGljYXRpb24vZ2VvK2pzb24iLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiMWI1MDZlMmYtZjU3Ni00YTlhLTk1NzAtNWY0MDY5OTFjZGIyIiwia3VybCI6Imh0dHBzOi8vb2djLmRlbW8uc2VjdXJlLWRpbWVuc2lvbnMuZGUva21zL2Rlay8xYjUwNmUyZi1mNTc2LTRhOWEtOTU3MC01ZjQwNjk5MWNkYjIifQ..YK40tObj6xY4jnkT.ai5wxo9uiLPZ0STOnnqmPMuBtZMu0qxbA3JYWzl_8cUPYogcWLrLLXhPP1FnqKnfews_EjJHt0XJuKoyhsXa3oQiGHadt3I6gGIlKDNNzSaB5bwTU31em8MSVmzm2m-O6ahKozMrjSoIwKvFh8X4Rgh7Tk-3GlglrBXJzw5qiznQDXGwz3ukGmHB0AVB78z12jJFmLcw7PsMOI5T3cTg5sGbTcySFgDxaFaV8pHRx-qbWVeKNb9aFcnIOLT1QWsA41p34nc7h8JwWy9779CU2PiBr9bmqE8aobDp_6JX8zRIeJgmcK0szi0LtK1TYAHzMYus5In2Z1ywsJeDACitr-TDQ1Pj8BjKzVVFVmOhdl9KnWhvLq8LvuLdijuR9T61anauWE4cLYgl6AYa4QDV2FVcgwn5G35yfrgSyvJi7_fZVeQhMesj2GbeslfvOciE9qfikoMjJ68g0NC8TbL8M7u_XIx6TQuJX1aXAXI1JgQrSlEX9KH9uBdeTqbzM9gmCDL9qy3WZgBPRzorSEi-H1hIObByfbysCG3JBh8nE4bnfuDBGcVlH-uCENOcZ98L1puXtBp57sscXFMb9mw2BrE-kJRBgzx-k_pO0jkVIo-4TIiz0Jo_SGTjDBHPMgyQswjy6C-l_RYBZFmF7MUBGuvT3kZYQyV2RVZBayMT2WFEFagrH6pTjGsqoDQC__oODkXJyufZBIpaBLiPj3SbhTmh_r0c0Q2-JS9XOBvt94pSe5j2PO1sBteoZ2dFjeM9URmwoScgTme478VqZErCHbN03KgguOWPp6InwnQUcI1yNTdCWju6EB4RaSwKzmN3caFNmwiEIiN4kutZy9Rr4TTSvels6u6waYQZYXAVh_yATOSfgXw3aWuITJGpq9xozNBuHLlZ6iJhGGGSeyRJe20swM_W-6OrPHML2Qu__tda_j2wt2_PO_stH0BW9K5s_wFDUfERbzw1-wKnbwYo-NIsm1fFUeHmNJrjiebPWUQfb5u3kMlV7U7_Qe6XUst7ZhEwDN_NYp4nZo5pCjuM1Cnp3eEoKwunRWsERI82oLTSFsYZi13xy-980NMpqCJNuvaSVHtCdBu2up7Z3tiNHZ-RrXlTa0QyfxEVABeX4L42zF0c57RLk0sb1jqKE30qsCjAz7LTW8ebSVp6Ef033pPC_Dk02zgLe9AK0xbDNPWTFHRaud3MC1zZsFHEcjfryKdBxdK51rU5q6s6EZcpL-_mkXrKkodTnagiEVYN9Nt-GMggR2xDvskjB5iqi28FTyLbHg0xc-tH2RGn7QeMYr4LK-KzPv2Ctsu3-x0mCwmHRaORqAecGt-t8PIXSy8emsveQqqFcD4_euh5M6cHLydipldKdTqroKqo6M-tiYsbWtcosc6_izapy7LGI8qP5E38P4jmA8ksjWiWFDSCIGbLTDamy3iN5owwkGGkQCg2lxgldrz1OVc9K2gecV1rNPtL_aTJ1Y_7OZpxiq9KNXpvwiUGdIhQbCkQW8csOkx9wKP4P0Kg9zdKcVUCCT9rc0yQxno82tm7U3H09HQHZx1SUB9xAly8umv0_RMDWLGAnhGI1xlNKT8rUhuhpsxBWQTgkFUyN_IRhKpvu3Q3pGXQzBvRnyYFk-VRS84aJjqjhEN3qChxYvF1voE5v0sS8b9zk2Vs0iwTa33D61zGk1ZZtygYN6hkfQCRCAzDdAqp6YPs1nXJ9iP4LEeXB9G9jqMg4vTf-ipwTnaYeW0FqS_MRLgj1ZOr3dBKEsb2cq7dPXv8JndfXL8WDKK1tdoHMhECdo_j_Lw7AXGjIg8Cs6zKG4GT1WO9wgbUQDKWhyUXRHMyowMJshm9_l-uVLCddupGilmUVSPCgV1iR2y0-eNtMgqtUG8eWhoLkbNc5Icbdbcc72JwF8TatKPJv0Z_YjAVo5s1pDGDwnaIDK9LgJ1t5nCOCsQR5FC2859QAwzg8HOkIByJvlJRKRJNxqmP-coBLuUw3wbnBm2rddUWEj7YhML9kqe0g0UhmOfdW93p1K8o8ojYBWcrNUXTbXThG1cfEhNb2BvCgve3EF-bub5P-TfL-iwQKn9vxrUWGyroTZZRXIhhm8PhzThg43nCLFik6dGOG27OoqsIm5d_sGs_sl7WgAc6aiENrtIoCFqPFJdvbyTAjIs5OZLWkZSEilRv3wnKSvrCnB6yz4OIqoO56jbDZumhV9gIrjztKc_c-4dH8ZB1AqEt1w7BIdh-mOG1yWNEn1ZsreLijlepeaDiBsRMtZO2xR7nJ0DOYUN_XGd5TtdgxTpgpgn_WR8uUmW8U_WBythu9oOHTXxDHwutv1nAu55AlT4Mrj2tYIWRBoFiCV6GgN65Od3tCTg7pKr-6FJI8Z-YHL-Q9Zzd0CDFnjhl-bGHOez7B8sXwD8u0PIqjnKjFl6qAfTWBcE2XJ0MiR7GC2xbSqDXXrQeFrz4G08MTS4_Vmv5c8h5pukaHSYvVU7wZmC9yBj_rBKxlQyVOnKkUPIbvwz3gQFA9mafrc6MvqRp5sys6eshcWTiFpA0fTAtnqtILdKP68a13kaXNPEZlPJcefFrW5djliMHoMMBYzqGqisv0EXUnmB5SVnMzbW5L_lG9Fr9Hu_0uUv589TgwCY89q1dpjDnZ0yzi0hUsOIf7dZ5xG-wktQwtBDqggvFKFxog717GjOaWOSz8B6IwQ333xaKBYzXLF3zW6xo_4u0edXBM5xhRuQkhZ-GMbTwFKzv0DSYwlEOkT-FOgTNpQE9CXH4ZzZwoXNLkehQmOsWmeJELKIymW3GFt7iczfysNa4jn20_3nIHGoyPG3pCtf0OAeMmGeIK9jPM0BcC90LIVxWfVwZ8RtrmB-pCLuCH40ikIRJR4zG5G0cs5KZg-k5xtcVdTTVDt4PVSu8OvU8ggV04-JNQwx73wY_bVUkMGLMpOhrrMXT-Wnv3Ck7uVwnTjmSflQtAU8F5YEUYC8tuTcgo5phTZsDIRacoI7dngCVxXtNGSyFWS0u-yWnmq9eHzHcmiL16B3tY2oLPVzCmvrlLPHjD2rCPCcXY1OUngV0vPvRugSaA8-FdVUbUNSybceqFzT9qoZFXTaJWrPgk84ydDpefbEWIf9SzfET1nzrtMd5QB8tVMKeS3y9IoUJXyGii3-PVMklJ05hRUCx90q-Lyt2_Bl0FKAqISzyCRZE4VmHpaPVt09JApBCwZ2UH6L0zrju-7hDhsoOIh50-zECrs6w6c1Bp9aMJsFHwW9onBNFK3L3TgLUqWy-_DEILvKJiBy3vonHVoso8gp81mCpsH6EY_YFAvrFmHyK6rQYNKIACGH37dbhiSkPiozibtay3NpMCRFikBskHPwCnamZ5EFMu36Zine4R0TtEMueTJPRkzjqEXG-uh4af5QijFNvmxqUchI2PHHs_HhrVAXBKgwQx_0k8fxcF7dKvkcRx38U6DbduLOLDoDm60lkNh8sdYY9UIX0U-DSD9nyn6OOgDlOlL1hLsTXi9lt7npWQOMyfL8qa_7a-BJDJ9Kq-DrOI6eWmGwRPnuvbbDmdvxHfplJXyEr_ap7K5GSp-FpaQwcaK5sQlTSBuzepG0-p9465aWl9z3Ulg6ywINjxGx7TIeEklMQVUdzUEhtqNlY27-fFpXKgLp4aY03o2NnB6bQHoeOy7Ulxpsfy3PDaLMiLxMw1RHVIkf-irmSiwNg13Nj7kxpkyac6ZyfhI0BP5l9IWKdfULKpkF0AqhKEbJDO_GDN67GnMQMnDsFOOwUJ32P-hKBu8IB1ohNNEzGy-bW2VvM5g3a2GzP9xyfLPolDoW8oO1J6UPWWY8Pk75hc176w5Ixozfu9ezQW5utcOxZOI5CA77bI25eoGGsXolwNwJmuTyd5pxTK2UNhcKGyh6c4CWreWn5PZWvd3COYTOP1w3vhUv3aiABvjkVzrhxAWXBKs_UoRVixpd0bn9sEr97BX5R7jPsQzgtKWdsYe4YZ3Qv2ReQMURlMZ9WGsUXoB9Ylh8PpEnpUXeAqHHcaLarsu96sEovh1PP2YGMbWd2l4L93ZwQQqOs6Jjs_evfphC8jsQ3-wo466BzTdbmW8fZZDWAUP6zW-uGCaBlxJnYTjaYAxbdXOJCEyutz1vtcWprCEj65Y8ePundDBaYviRfVsYIC3K_MgFjwnfM6J1KeoJj_sEoaurCZ0PIlwXE2NwQd19G8xvjkwP_rZ-6HtT-0HCJb0UMmNJfhpR7gAYL2xq4OGGHw6NzuNTHndzi5FNFRoIZeEqY8aKURcgPA8NGgKhinXCg9nWhel1oIxvkhBaozkkCS0hKb3xI1yGZjoxHf7CSc6133CFb1UnhmLd9PbvcchLDbpG-TYf8QZ_0mxTm_0rUuR6C-GE.2QtrrXOZGq6FRXYNaQZnTA"}]}'

Figure A.24

A.3.2.  Decode the JWT

See https://stackoverflow.com/questions/64616462/decode-jwt-header-python

test = json.loads(token)
obj = test['objects']
encdata = obj[0]['data']
encdata

Figure A.25

'eyJhbGciOiJkaXIiLCJjcml0IjpbImt1cmwiXSwiY3R5IjoiYXBwbGljYXRpb24vZ2VvK2pzb24iLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiMWI1MDZlMmYtZjU3Ni00YTlhLTk1NzAtNWY0MDY5OTFjZGIyIiwia3VybCI6Imh0dHBzOi8vb2djLmRlbW8uc2VjdXJlLWRpbWVuc2lvbnMuZGUva21zL2Rlay8xYjUwNmUyZi1mNTc2LTRhOWEtOTU3MC01ZjQwNjk5MWNkYjIifQ..YK40tObj6xY4jnkT.ai5wxo9uiLPZ0STOnnqmPMuBtZMu0qxbA3JYWzl_8cUPYogcWLrLLXhPP1FnqKnfews_EjJHt0XJuKoyhsXa3oQiGHadt3I6gGIlKDNNzSaB5bwTU31em8MSVmzm2m-O6ahKozMrjSoIwKvFh8X4Rgh7Tk-3GlglrBXJzw5qiznQDXGwz3ukGmHB0AVB78z12jJFmLcw7PsMOI5T3cTg5sGbTcySFgDxaFaV8pHRx-qbWVeKNb9aFcnIOLT1QWsA41p34nc7h8JwWy9779CU2PiBr9bmqE8aobDp_6JX8zRIeJgmcK0szi0LtK1TYAHzMYus5In2Z1ywsJeDACitr-TDQ1Pj8BjKzVVFVmOhdl9KnWhvLq8LvuLdijuR9T61anauWE4cLYgl6AYa4QDV2FVcgwn5G35yfrgSyvJi7_fZVeQhMesj2GbeslfvOciE9qfikoMjJ68g0NC8TbL8M7u_XIx6TQuJX1aXAXI1JgQrSlEX9KH9uBdeTqbzM9gmCDL9qy3WZgBPRzorSEi-H1hIObByfbysCG3JBh8nE4bnfuDBGcVlH-uCENOcZ98L1puXtBp57sscXFMb9mw2BrE-kJRBgzx-k_pO0jkVIo-4TIiz0Jo_SGTjDBHPMgyQswjy6C-l_RYBZFmF7MUBGuvT3kZYQyV2RVZBayMT2WFEFagrH6pTjGsqoDQC__oODkXJyufZBIpaBLiPj3SbhTmh_r0c0Q2-JS9XOBvt94pSe5j2PO1sBteoZ2dFjeM9URmwoScgTme478VqZErCHbN03KgguOWPp6InwnQUcI1yNTdCWju6EB4RaSwKzmN3caFNmwiEIiN4kutZy9Rr4TTSvels6u6waYQZYXAVh_yATOSfgXw3aWuITJGpq9xozNBuHLlZ6iJhGGGSeyRJe20swM_W-6OrPHML2Qu__tda_j2wt2_PO_stH0BW9K5s_wFDUfERbzw1-wKnbwYo-NIsm1fFUeHmNJrjiebPWUQfb5u3kMlV7U7_Qe6XUst7ZhEwDN_NYp4nZo5pCjuM1Cnp3eEoKwunRWsERI82oLTSFsYZi13xy-980NMpqCJNuvaSVHtCdBu2up7Z3tiNHZ-RrXlTa0QyfxEVABeX4L42zF0c57RLk0sb1jqKE30qsCjAz7LTW8ebSVp6Ef033pPC_Dk02zgLe9AK0xbDNPWTFHRaud3MC1zZsFHEcjfryKdBxdK51rU5q6s6EZcpL-_mkXrKkodTnagiEVYN9Nt-GMggR2xDvskjB5iqi28FTyLbHg0xc-tH2RGn7QeMYr4LK-KzPv2Ctsu3-x0mCwmHRaORqAecGt-t8PIXSy8emsveQqqFcD4_euh5M6cHLydipldKdTqroKqo6M-tiYsbWtcosc6_izapy7LGI8qP5E38P4jmA8ksjWiWFDSCIGbLTDamy3iN5owwkGGkQCg2lxgldrz1OVc9K2gecV1rNPtL_aTJ1Y_7OZpxiq9KNXpvwiUGdIhQbCkQW8csOkx9wKP4P0Kg9zdKcVUCCT9rc0yQxno82tm7U3H09HQHZx1SUB9xAly8umv0_RMDWLGAnhGI1xlNKT8rUhuhpsxBWQTgkFUyN_IRhKpvu3Q3pGXQzBvRnyYFk-VRS84aJjqjhEN3qChxYvF1voE5v0sS8b9zk2Vs0iwTa33D61zGk1ZZtygYN6hkfQCRCAzDdAqp6YPs1nXJ9iP4LEeXB9G9jqMg4vTf-ipwTnaYeW0FqS_MRLgj1ZOr3dBKEsb2cq7dPXv8JndfXL8WDKK1tdoHMhECdo_j_Lw7AXGjIg8Cs6zKG4GT1WO9wgbUQDKWhyUXRHMyowMJshm9_l-uVLCddupGilmUVSPCgV1iR2y0-eNtMgqtUG8eWhoLkbNc5Icbdbcc72JwF8TatKPJv0Z_YjAVo5s1pDGDwnaIDK9LgJ1t5nCOCsQR5FC2859QAwzg8HOkIByJvlJRKRJNxqmP-coBLuUw3wbnBm2rddUWEj7YhML9kqe0g0UhmOfdW93p1K8o8ojYBWcrNUXTbXThG1cfEhNb2BvCgve3EF-bub5P-TfL-iwQKn9vxrUWGyroTZZRXIhhm8PhzThg43nCLFik6dGOG27OoqsIm5d_sGs_sl7WgAc6aiENrtIoCFqPFJdvbyTAjIs5OZLWkZSEilRv3wnKSvrCnB6yz4OIqoO56jbDZumhV9gIrjztKc_c-4dH8ZB1AqEt1w7BIdh-mOG1yWNEn1ZsreLijlepeaDiBsRMtZO2xR7nJ0DOYUN_XGd5TtdgxTpgpgn_WR8uUmW8U_WBythu9oOHTXxDHwutv1nAu55AlT4Mrj2tYIWRBoFiCV6GgN65Od3tCTg7pKr-6FJI8Z-YHL-Q9Zzd0CDFnjhl-bGHOez7B8sXwD8u0PIqjnKjFl6qAfTWBcE2XJ0MiR7GC2xbSqDXXrQeFrz4G08MTS4_Vmv5c8h5pukaHSYvVU7wZmC9yBj_rBKxlQyVOnKkUPIbvwz3gQFA9mafrc6MvqRp5sys6eshcWTiFpA0fTAtnqtILdKP68a13kaXNPEZlPJcefFrW5djliMHoMMBYzqGqisv0EXUnmB5SVnMzbW5L_lG9Fr9Hu_0uUv589TgwCY89q1dpjDnZ0yzi0hUsOIf7dZ5xG-wktQwtBDqggvFKFxog717GjOaWOSz8B6IwQ333xaKBYzXLF3zW6xo_4u0edXBM5xhRuQkhZ-GMbTwFKzv0DSYwlEOkT-FOgTNpQE9CXH4ZzZwoXNLkehQmOsWmeJELKIymW3GFt7iczfysNa4jn20_3nIHGoyPG3pCtf0OAeMmGeIK9jPM0BcC90LIVxWfVwZ8RtrmB-pCLuCH40ikIRJR4zG5G0cs5KZg-k5xtcVdTTVDt4PVSu8OvU8ggV04-JNQwx73wY_bVUkMGLMpOhrrMXT-Wnv3Ck7uVwnTjmSflQtAU8F5YEUYC8tuTcgo5phTZsDIRacoI7dngCVxXtNGSyFWS0u-yWnmq9eHzHcmiL16B3tY2oLPVzCmvrlLPHjD2rCPCcXY1OUngV0vPvRugSaA8-FdVUbUNSybceqFzT9qoZFXTaJWrPgk84ydDpefbEWIf9SzfET1nzrtMd5QB8tVMKeS3y9IoUJXyGii3-PVMklJ05hRUCx90q-Lyt2_Bl0FKAqISzyCRZE4VmHpaPVt09JApBCwZ2UH6L0zrju-7hDhsoOIh50-zECrs6w6c1Bp9aMJsFHwW9onBNFK3L3TgLUqWy-_DEILvKJiBy3vonHVoso8gp81mCpsH6EY_YFAvrFmHyK6rQYNKIACGH37dbhiSkPiozibtay3NpMCRFikBskHPwCnamZ5EFMu36Zine4R0TtEMueTJPRkzjqEXG-uh4af5QijFNvmxqUchI2PHHs_HhrVAXBKgwQx_0k8fxcF7dKvkcRx38U6DbduLOLDoDm60lkNh8sdYY9UIX0U-DSD9nyn6OOgDlOlL1hLsTXi9lt7npWQOMyfL8qa_7a-BJDJ9Kq-DrOI6eWmGwRPnuvbbDmdvxHfplJXyEr_ap7K5GSp-FpaQwcaK5sQlTSBuzepG0-p9465aWl9z3Ulg6ywINjxGx7TIeEklMQVUdzUEhtqNlY27-fFpXKgLp4aY03o2NnB6bQHoeOy7Ulxpsfy3PDaLMiLxMw1RHVIkf-irmSiwNg13Nj7kxpkyac6ZyfhI0BP5l9IWKdfULKpkF0AqhKEbJDO_GDN67GnMQMnDsFOOwUJ32P-hKBu8IB1ohNNEzGy-bW2VvM5g3a2GzP9xyfLPolDoW8oO1J6UPWWY8Pk75hc176w5Ixozfu9ezQW5utcOxZOI5CA77bI25eoGGsXolwNwJmuTyd5pxTK2UNhcKGyh6c4CWreWn5PZWvd3COYTOP1w3vhUv3aiABvjkVzrhxAWXBKs_UoRVixpd0bn9sEr97BX5R7jPsQzgtKWdsYe4YZ3Qv2ReQMURlMZ9WGsUXoB9Ylh8PpEnpUXeAqHHcaLarsu96sEovh1PP2YGMbWd2l4L93ZwQQqOs6Jjs_evfphC8jsQ3-wo466BzTdbmW8fZZDWAUP6zW-uGCaBlxJnYTjaYAxbdXOJCEyutz1vtcWprCEj65Y8ePundDBaYviRfVsYIC3K_MgFjwnfM6J1KeoJj_sEoaurCZ0PIlwXE2NwQd19G8xvjkwP_rZ-6HtT-0HCJb0UMmNJfhpR7gAYL2xq4OGGHw6NzuNTHndzi5FNFRoIZeEqY8aKURcgPA8NGgKhinXCg9nWhel1oIxvkhBaozkkCS0hKb3xI1yGZjoxHf7CSc6133CFb1UnhmLd9PbvcchLDbpG-TYf8QZ_0mxTm_0rUuR6C-GE.2QtrrXOZGq6FRXYNaQZnTA'

Figure A.26

import json
from jwcrypto.common import base64url_decode

parts = encdata.split('.')
# get the first part of the token
jsondata = base64url_decode(parts[0])
data = json.loads(jsondata)
data

Figure A.27

{'alg': 'dir',
 'crit': ['kurl'],
 'cty': 'application/geo+json',
 'enc': 'A256GCM',
 'kid': '1b506e2f-f576-4a9a-9570-5f406991cdb2',
 'kurl': 'https://ogc.demo.secure-dimensions.de/kms/dek/1b506e2f-f576-4a9a-9570-5f406991cdb2'}

Figure A.28

kid = data['kid']
kid

Figure A.29

'1b506e2f-f576-4a9a-9570-5f406991cdb2'

Figure A.30

# kurl is a custom field, used for the testbed.
kurl = data['kurl']
kurl

Figure A.31

'https://ogc.demo.secure-dimensions.de/kms/dek/1b506e2f-f576-4a9a-9570-5f406991cdb2'

Figure A.32

A.3.3.  Get the key from KMS via de kid

See https://ogc.demo.secure-dimensions.de/kms/developers

# response = requests.get("https://ogc.demo.secure-dimensions.de/kms/dek/" + kid ,
response = requests.get( kurl ,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

data = json.loads(response.text)
data

Figure A.33

{'kid': '1b506e2f-f576-4a9a-9570-5f406991cdb2',
 'alg': 'A256GCM',
 'kty': 'oct',
 'k': 'nPOHB8puwtwdAnqA4a5pb-iKOp9RgO77vdgUvGpyrOU',
 'issuer': 'https://ogc.demo.secure-dimensions.de/pycsw',
 'expires': 1666366239,
 'issued_at': 1666365939,
 'aud': '4f9610ac-9d1f-3797-6a41-6b18f9852572',
 'sub': '4e7f5c63-0552-30f5-8b56-03e634ecd978'}

Figure A.34

A.3.4.  Decode the payload

import jwt
from jwcrypto import jwk, jwe
from jwcrypto.common import JWSEHeaderParameter

# create the DEK from the response obtained from the KMS.
dek = jwk.JWK.from_json(response.text)

registry = {
    'kurl': JWSEHeaderParameter(description='Key URL', mustprotect=True, supported=True, check_fn=None)
}

jwe_token = jwe.JWE( header_registry = registry )
jwe_token.deserialize(encdata)
jwe_token.decrypt(dek)

decrypted_payload = jwe_token.payload

data = json.loads(decrypted_payload)
jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

Figure A.35

{
  
"type": "FeatureCollection",
  
"features": [
     
{
        
"id": "05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99",
        
"type": "Feature",
        
"geometry": {
           
"type": "Polygon",
           
"coordinates": [
              
[
                 
[
                    
2.53,
                    
50.67
                 
],
                 
[
                    
2.53,
                    
51.51
                 
],
                 
[
                    
5.92,
                    
51.51
                 
],
                 
[
                    
5.92,
                    
50.67
                 
],
                 
[
                    
2.53,
                    
50.67
                 
]
              
]
           
]
        
},
        
"properties": {
           
"externalId": "05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99",
           
"datetime": "2022-04-12",
           
"start_datetime": "2013-11-28",
           
"end_datetime": "1900-01-01",
           
"recordUpdated": "2022-07-21T22:40:13Z",
           
"type": "series",
           
"created": "2021-09-15",
           
"updated": "2022-04-12",
           
"title": "Interessante plaatsen (POI)",
           
"description": "Datasetreeks van datasets met interessante plaatsen",
           
"associations": [
              
{
                 
"href": "https://geoservices.informatievlaanderen.be/overdrachtdiensten/POI/wfs?service=WFS&version=2.0.0&request=GetCapabilities",
                 
"name": null,
                 
"description": "WFS Interessante plaatsen",
                 
"type": "OGC:WFS-2.0.0-http-get-capabilities",
                 
"rel": "OGC:WFS-2.0.0-http-get-capabilities"
              
},
              
{
                 
"href": "https://geoservices.informatievlaanderen.be/overdrachtdiensten/POI/wfs?request=GetFeature&version=2.0.0&typename=POI:POI&count=1",
                 
"name": "POI:POI",
                 
"description": "Points of Interest",
                 
"type": "OGC:WFS-2.0.0-http-get-feature",
                 
"rel": "OGC:WFS-2.0.0-http-get-feature"
              
}
           
],
           
"extent": {
              
"spatial": {
                 
"bbox": [
                    
[
                       
2.53,
                       
50.67,
                       
5.92,
                       
51.51
                    
]
                 
],
                 
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
              
}
           
}
        
},
        
"links": [
           
{
              
"rel": "via",
              
"type": "application/xml",
              
"title": "This document as XML",
              
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99?f=xml",
              
"hreflang": "en-US"
           
}
        
],
        
"assets": {}
     
}
  
],
  
"links": [
     
{
        
"rel": "self",
        
"type": "application/dcs+geo",
        
"title": "This document as DCS + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&limit=1&type=series&f=dcs+geo",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose",
        
"title": "This document as JOSE + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&limit=1&type=series&f=jose",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose;profile=jws",
        
"title": "This document as JWS",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&limit=1&type=series&f=jws",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/geo+json",
        
"title": "This document as GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99?f=json",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "text/html",
        
"title": "This document as HTML",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/05f9e795-b1ab-4ff7-9d5b-96c8c6d19d99?f=html",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "collection",
        
"type": "application/json",
        
"title": "Collection URL",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "next",
        
"type": "application/dcs+geo",
        
"title": "items (next)",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items?key_challenge=123&limit=1&type=series&f=dcs+geo&offset=1",
        
"hreflang": "en-US"
     
}
  
],
  
"numberMatched": 4,
  
"numberReturned": 1,
  
"bbox": [
     
2.53,
     
50.67,
     
5.92,
     
51.51
  
]
}

Figure A.36

show_on_map(data)

Figure A.37

Make this Notebook Trusted to load map: File → Trust Notebook

A.4.  D113 GET /items/{item-id} with DCS (KMS)

Example: 3.1
> Access the OGC API-Records D113 /items/{item-id} with DCS (application/dcs+geo)

# Get the access token from https://ogc.demo.secure-dimensions.de/token-app/
response = requests.get(endpoint_item + '?key_challenge=123',
    verify=bool(verify_ssl),
    headers={'Accept': 'application/dcs+geo', 'Authorization':  'Bearer ' + access_token})

response

Figure A.38

<Response [200]>

Figure A.39

A.4.1.  JWT

Catalogue response corresponds to a JWT. The complete response is a JWE. The syntax is defined at https://openid.net/specs/draft-jones-json-web-encryption-02.html Contains 3 parts separated by dots…

token = response.text
token

Figure A.40

'{"type": "dcs+geo", "timestamp": "2022-10-21T17:25:42+02:00", "objects": [{"metadata": {"confidentiality_information": {"policy_identifier": "TB18", "classification": "unclassified"}, "creation_data_time": "2022-10-21T17:25:42+02:00", "number_matched": 1, "number_returned": 1, "bbox": {"bbox": [[2.83, 51.18, 3.02, 51.28]], "crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"}, "links": [{"rel": "self", "type": "application/dcs+geo", "title": "This document as DCS + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?key_challenge=123&#x26;f=dcs+geo&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}, {&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/jose&#x22;, &#x22;title&#x22;: &#x22;This document as JOSE + GeoJSON&#x22;, &#x22;href&#x22;: &#x22;https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?key_challenge=123&#x26;f=jose&#x22;, &#x22;hreflang&#x22;: &#x22;en-US&#x22;}, {&#x22;rel&#x22;: &#x22;alternate&#x22;, &#x22;type&#x22;: &#x22;application/jose;profile=jws", "title": "This document as JWS", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jws", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/geo+json", "title": "This document as GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=json", "hreflang": "en-US"}, {"rel": "alternate", "type": "text/html", "title": "This document as HTML", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=html", "hreflang": "en-US"}, {"rel": "collection", "type": "application/json", "title": "Collection URL", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main", "hreflang": "en-US"}]}, "data": "eyJhbGciOiJkaXIiLCJjcml0IjpbImt1cmwiXSwiY3R5IjoiYXBwbGljYXRpb24vZ2VvK2pzb24iLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiNmE5ZTU3MjctMzRjNi00MDQ1LWE0MmQtNzEyNWNiMzY2ZDJhIiwia3VybCI6Imh0dHBzOi8vb2djLmRlbW8uc2VjdXJlLWRpbWVuc2lvbnMuZGUva21zL2Rlay82YTllNTcyNy0zNGM2LTQwNDUtYTQyZC03MTI1Y2IzNjZkMmEifQ..hnfAseeN7cvoodM9.AGmIrQ7WeCJE0OTb0_aWTCN3ETNWrZZ-J9lnQlWD2QmJsIsScTYV70AoEMcqEl7W5OOmU_SfKEdvRiWgN6uPFvqMT8T99Hiv4CJU-m-8q46ob4vuqZ4fmSP6-zd5iJV-5l9-Sga9QwpZDzST-wbARHtcvDo-FUoUk9N2YXts4zEnCxit_YCrQ_ZIbV_odAfGl-iv31XbVZyyB_lye3zK3il5o--jPgdRRZwhqeoUaI8Uc9TevzU_8ffgw5UpYI_8Wf2IWKzP8cqciXmnE39WMGPI3-B3ZKtMGDtR4QOmdX8XVU56hYTWfYA8Rl8QJB0YOcfoongd1TzbZij9dV4DkY3-RIbhbGRMr3yUz1HcGA9OU0anC8JbbuOEdfdnBM5yPgaX9IL0i2ZJoi8xLB3ALYyP9vQJeY8RobS97ilSApIVEH4XxNq08ZyKFd1YjBdEEWObCawa3pWTCBwh2orlyiQVLOlE-PyGVw4u0Ge-GyRoAEbiOc3l_sKJA7qacaSuWZiI-xf6f6VAIRVLsb7EJj2xMg0KS5OyHQE2UUnTyRT5C0eWa26RGa3sqJ3FlHgy6ypSDMelN_5nWbpDzwJRG-EBQJeCBVPRq483cXmkRL0JlXR9yDw1LbfsOPY3ThsePPkdEDSRzYh-QN4Fz717TymMIP6lAXpdJEKRqMsD54GFNnmC6Dc-somEFv649wMdq_58o3TB2i9FevZhIuTQXwaHuufw6XrIFIOjpPkrHTkrsNZgXnpjnuRMSIGcjoTcqVNZ9oLzAiMOcMs5TK01oz8Mgn3doDjI1LzWnATf-Dm2FcOZuNj1sN4CGsGIUiYKLUvO0qnuu9ssgUuzCczJgQHQl8gIdpFKApyAuI52qiVi0gc6vwAFz2G8o21SwaW4GGdxLk1qcAGr54CmWOup617iinduyRqo6oQNOODKkIsu0Qa2G2nRUJNrVJLIggkepcql_zd0HQUVBug_dKCtsa_1oKmdIu-kvP3CVMmJF8AHIj6gu6PaogBvmp7KEWtC2kV4wNPnqmUp9r5vdqVuNP9Id3NmWFeAG7knM2huRZI-F44fnPSjIcj5PWLF5x9eQxXAG6ClOsBMVzilap7XNrPSQgyONHGxYre1HqGFMnD2RTLYBgUpumqFypSYMWURoWV0R77TBZaiQGjSwZ7Rb_myygx18TdLuDYUp_rIfZ8Ik8_LujTD0wDfHo1zWvcJ3XTQeiRz76ZJmK8-cizz1QwtaEGM7nOtK0umuap3dai3hycLUI-gGb_PgyszTxmn5N6L9B40mEMNaa_Yp8zNBft6-lSSsbOK0a3uEGj8u8sGoaiCeGy2W6RHoArzT7XAeedfCCAbq4_PiWph2iZ647DadgqrdqZKI6h5e-pUYUUH4RxIp6pYFfoB00OhYBPt5QbDK_-zPnhxkrgNkATQGFE18I94cbq4DliS0j-cCuQ5UBk2SJUqFapCZ2YK8qPE0lZf2WbLWpLRfKBUXeKeV2nRjYQWvw9g90DTPHmAa-JjKeo1ky8nfMavmVtxWrQ2fCN5d32gFuZd58zuvdDkFJ7-B1BccZ-kQ1JI50B-kUOQvwDg3P5ZszG-HNqyLCZ98FdaEuHgYJrFjg6FMJvBGnDxUW4xZAt_4rDnIvbySp7pxzYG0lpStMFg5F2aRd9gv5VIrcHfopy2PuSZ29M9P7pDdP6qqDeJ0oD4yqahmxa3m3IBLNdEcfYKWf0UZI7Q5Xzjx1GMynMhhq0ZpYGbdocz9GerLluKsZzqtOz--a-uvI7-AokVAJICvnd2Viipd-5QVTMwRDU3fq_6tEsDNY7Tp8uKYt65DoaRucplzHk32HeDgfXC2t_X_clCQR6XM6qgjH6uGKihGCxhlLIEfKIMEpuXbrTu5pOWPrfs8E8OG88SlkfKJxahw2GhLgWgoTh8-uL-ka9wVJNtdbi3wlbWdyAoBn7QVjGGd866NkcHZEfUA0crxBAEm-bmoEgQ32E5FlVQGSwbWG3xmQtbRSkI6Y1a7atL1blnuzTMKSpZO7QWkthlai-S_VmxRTFf3DuXeTFYDKC9ridb5isU6E18Q4JJKf7tj2fOdRt4DERLtVa8CCnza8TLSgI2R5rd5UvAqD0S-rsVwhkZjl2AfnI6Mc791qPcAIgO2V6b_PwnOGZlHuI6qwUHwu7e2y9HBSJ4F3K92As0ALPfFJ4LTbky33Uw9iQ11927-7eQME3GnQK_5ReNJTAOuVP03yROnXnoPmHzKibjBAjB93SYsebWMmPjwVxBYVcJSVaGe4iHaOcVuCaih_yk9pXj14rwk9XxM95EuwQGKaDsjmoAfwcRinYyiy3syR7LF0b5x0wP6Gu_7qHXEAvQuP2oSRdIYJ8VcHDDX3JDaIpMPHmAr08I6XtZBazj1j2-cctICTNtZY3EYc_II7ckhHARYdra3kkVS-387uajG9FxRNuOnTAl_9w5-YI_8rTm6JFAeD7ATrYt6nxrP_B5rklUD1vN4sAu7J7kLJOUHrmpCPXmrHyF_TKPG4SMDzzhxivE95iBJMnx3Odc8F1qbvjpDg4aHuVYT1HvcODCnIviMtvEyyRs_FUIrGthCAsiPBmDxzApk8xONMmBfnFBPvUjKNwwHGAXE6XqmtcMv3_I6MlsmNCODNb3UQsYOGQJxn9ZaS2twA_2vDLEK44eexgVc77oyNs1kPE19a0ptgZrxOxvSIjtMhxK2r1JER5EFY-Z7r817lLCPyl9bcPJMy5ZPGPDbwDXGRHNcWfLEIkStRf6LyxL82yhVRL18ALdRuCUVLaRIk9Xh3-YS9CXBKS31372R9bPb4op-aWj3gbDDB-5xFIfBoU3lqjvHs91BdHk5ScaP0sHqwYyiJ3C_iWxm12WzYXUjFRDz6xuKkS5OvQEcs9_Zmg2Yc9Th36g-mop2gJCDtQRMgT3mtGG6uwlmZGsSiamsHeZJCQQwAasWf27nR5e381BPkcNHZR4isGDFu3ck0Xe_aboKwWOKvaCX0rVDK9awQV5PSh5brvp3a-TJaGQpapTibiL1P5VcdU4Irp-SkzKNIJfkZ-lPJGVhZvxFBMcngGJU7rDF5PbeHblRM0aD414xR8Hn514XziTQsZTQQlF9Z5nBylo1ln1XbXaHHTZVyQw_NhMt5w_PEgNmsu1iRFSB4awfKBt9V-oMwRLo_qKA-hKJLmbT0feyFsp4mRoCDFl6o_cIVeLneiflvDp9MTEQBeM7dbfoiQs1JVpXtb6pgJWi4f6y-VFuFQ_D371MdebCXdBElzPf9LPgLcJw5XcGc8zO2zsKXZLukxupIgaPjwuFc14mM23jWra6MSnaMKrBxgW9rU8ivfxVkLUBESQbHGrqovh1g0JBXAK6Gx-nlPazcZK2LfBNhlAHNTmJq7IdNbaQFlKWEoRL6l1-DyemaeVuido3YUNW4O8rDsUKiEX9VS9s15eIbtOJ3pays1_nMRWHXKF_mULi3ME4UP_iwYphTl_vAPaTqkWzXGEq23GfMOF-HkwC8jdmeo8dIC1F7O9QJ2F3Fh8XPQs7HbBRUNtcsgUEl1igtACz5I5hTl075jIoBolSSIaDiCfdj3tj0XSjXRnm0plHxdjOpxib2skKUscR8OUudaB48oRCE3pdQSjKubG_ZZNruQrVmcOW2MgZ-DNjEgyIO3CT_DO8F70Zcy7jXzKILi61iSABPh-3MP4qGmRU0cCf8HpkbnuD_8-ah029Z_9fi6ghLuoa-6FPgSx56G80hnD0s3l44ks3d_GAtDJu33eD_mA40cRndbOWDKqKH-2Ch0ZJXXXHBYB7R-Vuq6LyHBasXYD_spVlkO25nH_3ZIHd0fa5EGct-Wf3twtz2CQEBQwWsjZrMbsVSLkztvUn3lk2CDqoqoU8lm5-bM7SMHfSHsJEgQZK-lQWXHdQSjuXppZpMbinDp-fv55kE0ZFtcVPsRvam4LS3L4OjghtMf6uRrzWS1dFG0NZ8Na4-WiIjQwuGroz8X1ulx73UwJabrhGQvmA8BuhpofqYrCyN79C_R8YuwGHNEOXbgRXprZ4syE1mlr0CvR7txC2D_F_ItmE3QMLAmSmam27jeDqTgQhyTSgozASPmV151tLcxfRjIoSAzBUJw-W6UmnRICExZOP0Mw674P5KFzH6veckK21puh21iTiWJ6HZMtTa7GxM1xu_ArZAZmpxZ1cn2KiUaZ2UUcD-KykvfOmF97jF4pTuwcJmzoFqFdq_znZYBsDG_01cEqQ-kbBAafj8s6Q-WtGdzhqifpV6rlWpwVpx_NNloI-iUItx79nBiYnGuzTA5bUoihIMVFHGS_zP7hjssm8Bfq0hAIqrYHdV7VU_2s1RVFBESW5BzE1E55f3wslshXr_FgcHFy7Kr72rb5tk1j3ZgsfCUuuaYDA7LlqeevYzU_G1zNP4CH8Mvlo58V2M7lX6JT7664Yi6eTmw4rr8bmNgQyENT4915mGetg8c0mLNI25Gz5q4NKl3cxZkqaQv8cXZ6GKTeJxYaQn78d-UNaJGZ7oqJ1Qmr2zpmdcNnJxlx07knVy8UNVzfaCuevIFnSn8VIWB9_SQyQ5YNhHIC445FV62ZNh5KgiwU2o0S1ia8zbVbJk3yUm85_iSQdFZbhtrTrp9ss92sf2BRr121mlR7tV5fXssiovUjYstppcIzHUxmTHFHh8KUhS2kqhP60nouVeHobMOuuWW37Y92nnU-15mfcUT1z7dqp--Fm31QzysOn4B6tieEDRZpssea_CHVnwPQS1NfBpx3t62ru6cNfa3qfjoBQijaO_7mVWBk1-uw6JaX82U25mwOePwof26gWDu_G33cHvfSN909ToSqSUtXs4kXxvoSfTAwV2Bz3OjIrIvk3qnfUpJXCMLf3fQD9em1ze9V_8P5Tw36kU2_BgfJRyBOW5pCWkJZGNRpl8XnfzNtd-1j7qfal71G1IcQ2UhQEZ7l0wgtr5MsbE4VUMZMmMoHIl7E9gwRVxVH8Mz1J9PojKvYrySbX1AAp9_zxtnMX_BBJ6aqP7nCC9Ju25l6Lfc9NPXq8WybMDvHhFy-YOwwc0MJ3S6SqoXaxmhxrdcCNGZfwFqJxSOydlRifZ5zC3XDdCSHPw907QMI5_esmFMhWr6FEFBHHNT8YExPOeojpRWDMsHqyb6wwH707o4SPm0Z81pJ1Sm918BTn_15Sg9nLBGv_PBoJJfgea88RnD50F2V39bDWYkUnNK_nFpzh2Gn7IQwoEZJWnuQakG-kON3aTb4XoRwpdkjClZO9bhKA4DNX6gIWPWme_c2H3SXORUYsLJKC91vuJki-_Bjg-6SH3uzuKwoX02HjaScY6mXmHBHNJCHC400VqjKE-mjDEHSBLIFn5LW4mKRk4soaw1LRXhIR9QQbViKKsX6wg1tNhdOlhj8UGtDKKJuxgROD0bB3SWt8WOnhyrR9dX2xkCxrBL3LTWzxTDtQldsVw2MBn0YKYNirc_-GNaUiE4tG0VJqUquFLQ4ZZcPTPgHDySKi2TO8RkXXYNtHcMzCH6evONOYDOv1nD2p4uhIGifX6JzJm4zL4_zMli2NhWBKsRGc918zncLaISfvy0xActIhYeHSUIdlBEA5cX-xTtIV9K-58cq0IgmfPXq3VbEA7kQBK633PkJlcgUjGwttFkyF1D-1rvkwcRyNMmRHIe_tyPrkgIiUJAyQvIYrnHV4LtLyuVuTe8TaXa7NCSZ5L6jMWuGU7d4WL-lPufvMVsvC6VtMoo42z5NpdxUq99rwxCym6C6mUmf8i0h6jis6VleMWg-ryQRSoooAsoBWOfsdqSv5EU7a4PJ1U907Rt_OoLspquvq8wNsmmEmH1Q.B6wQyyEzI-KmP_w9UAMT0A"}]}'

Figure A.41

A.4.2.  Decode the JWT

See https://stackoverflow.com/questions/64616462/decode-jwt-header-python

test = json.loads(token)
obj = test['objects']
encdata = obj[0]['data']
encdata

Figure A.42

'eyJhbGciOiJkaXIiLCJjcml0IjpbImt1cmwiXSwiY3R5IjoiYXBwbGljYXRpb24vZ2VvK2pzb24iLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiNmE5ZTU3MjctMzRjNi00MDQ1LWE0MmQtNzEyNWNiMzY2ZDJhIiwia3VybCI6Imh0dHBzOi8vb2djLmRlbW8uc2VjdXJlLWRpbWVuc2lvbnMuZGUva21zL2Rlay82YTllNTcyNy0zNGM2LTQwNDUtYTQyZC03MTI1Y2IzNjZkMmEifQ..hnfAseeN7cvoodM9.AGmIrQ7WeCJE0OTb0_aWTCN3ETNWrZZ-J9lnQlWD2QmJsIsScTYV70AoEMcqEl7W5OOmU_SfKEdvRiWgN6uPFvqMT8T99Hiv4CJU-m-8q46ob4vuqZ4fmSP6-zd5iJV-5l9-Sga9QwpZDzST-wbARHtcvDo-FUoUk9N2YXts4zEnCxit_YCrQ_ZIbV_odAfGl-iv31XbVZyyB_lye3zK3il5o--jPgdRRZwhqeoUaI8Uc9TevzU_8ffgw5UpYI_8Wf2IWKzP8cqciXmnE39WMGPI3-B3ZKtMGDtR4QOmdX8XVU56hYTWfYA8Rl8QJB0YOcfoongd1TzbZij9dV4DkY3-RIbhbGRMr3yUz1HcGA9OU0anC8JbbuOEdfdnBM5yPgaX9IL0i2ZJoi8xLB3ALYyP9vQJeY8RobS97ilSApIVEH4XxNq08ZyKFd1YjBdEEWObCawa3pWTCBwh2orlyiQVLOlE-PyGVw4u0Ge-GyRoAEbiOc3l_sKJA7qacaSuWZiI-xf6f6VAIRVLsb7EJj2xMg0KS5OyHQE2UUnTyRT5C0eWa26RGa3sqJ3FlHgy6ypSDMelN_5nWbpDzwJRG-EBQJeCBVPRq483cXmkRL0JlXR9yDw1LbfsOPY3ThsePPkdEDSRzYh-QN4Fz717TymMIP6lAXpdJEKRqMsD54GFNnmC6Dc-somEFv649wMdq_58o3TB2i9FevZhIuTQXwaHuufw6XrIFIOjpPkrHTkrsNZgXnpjnuRMSIGcjoTcqVNZ9oLzAiMOcMs5TK01oz8Mgn3doDjI1LzWnATf-Dm2FcOZuNj1sN4CGsGIUiYKLUvO0qnuu9ssgUuzCczJgQHQl8gIdpFKApyAuI52qiVi0gc6vwAFz2G8o21SwaW4GGdxLk1qcAGr54CmWOup617iinduyRqo6oQNOODKkIsu0Qa2G2nRUJNrVJLIggkepcql_zd0HQUVBug_dKCtsa_1oKmdIu-kvP3CVMmJF8AHIj6gu6PaogBvmp7KEWtC2kV4wNPnqmUp9r5vdqVuNP9Id3NmWFeAG7knM2huRZI-F44fnPSjIcj5PWLF5x9eQxXAG6ClOsBMVzilap7XNrPSQgyONHGxYre1HqGFMnD2RTLYBgUpumqFypSYMWURoWV0R77TBZaiQGjSwZ7Rb_myygx18TdLuDYUp_rIfZ8Ik8_LujTD0wDfHo1zWvcJ3XTQeiRz76ZJmK8-cizz1QwtaEGM7nOtK0umuap3dai3hycLUI-gGb_PgyszTxmn5N6L9B40mEMNaa_Yp8zNBft6-lSSsbOK0a3uEGj8u8sGoaiCeGy2W6RHoArzT7XAeedfCCAbq4_PiWph2iZ647DadgqrdqZKI6h5e-pUYUUH4RxIp6pYFfoB00OhYBPt5QbDK_-zPnhxkrgNkATQGFE18I94cbq4DliS0j-cCuQ5UBk2SJUqFapCZ2YK8qPE0lZf2WbLWpLRfKBUXeKeV2nRjYQWvw9g90DTPHmAa-JjKeo1ky8nfMavmVtxWrQ2fCN5d32gFuZd58zuvdDkFJ7-B1BccZ-kQ1JI50B-kUOQvwDg3P5ZszG-HNqyLCZ98FdaEuHgYJrFjg6FMJvBGnDxUW4xZAt_4rDnIvbySp7pxzYG0lpStMFg5F2aRd9gv5VIrcHfopy2PuSZ29M9P7pDdP6qqDeJ0oD4yqahmxa3m3IBLNdEcfYKWf0UZI7Q5Xzjx1GMynMhhq0ZpYGbdocz9GerLluKsZzqtOz--a-uvI7-AokVAJICvnd2Viipd-5QVTMwRDU3fq_6tEsDNY7Tp8uKYt65DoaRucplzHk32HeDgfXC2t_X_clCQR6XM6qgjH6uGKihGCxhlLIEfKIMEpuXbrTu5pOWPrfs8E8OG88SlkfKJxahw2GhLgWgoTh8-uL-ka9wVJNtdbi3wlbWdyAoBn7QVjGGd866NkcHZEfUA0crxBAEm-bmoEgQ32E5FlVQGSwbWG3xmQtbRSkI6Y1a7atL1blnuzTMKSpZO7QWkthlai-S_VmxRTFf3DuXeTFYDKC9ridb5isU6E18Q4JJKf7tj2fOdRt4DERLtVa8CCnza8TLSgI2R5rd5UvAqD0S-rsVwhkZjl2AfnI6Mc791qPcAIgO2V6b_PwnOGZlHuI6qwUHwu7e2y9HBSJ4F3K92As0ALPfFJ4LTbky33Uw9iQ11927-7eQME3GnQK_5ReNJTAOuVP03yROnXnoPmHzKibjBAjB93SYsebWMmPjwVxBYVcJSVaGe4iHaOcVuCaih_yk9pXj14rwk9XxM95EuwQGKaDsjmoAfwcRinYyiy3syR7LF0b5x0wP6Gu_7qHXEAvQuP2oSRdIYJ8VcHDDX3JDaIpMPHmAr08I6XtZBazj1j2-cctICTNtZY3EYc_II7ckhHARYdra3kkVS-387uajG9FxRNuOnTAl_9w5-YI_8rTm6JFAeD7ATrYt6nxrP_B5rklUD1vN4sAu7J7kLJOUHrmpCPXmrHyF_TKPG4SMDzzhxivE95iBJMnx3Odc8F1qbvjpDg4aHuVYT1HvcODCnIviMtvEyyRs_FUIrGthCAsiPBmDxzApk8xONMmBfnFBPvUjKNwwHGAXE6XqmtcMv3_I6MlsmNCODNb3UQsYOGQJxn9ZaS2twA_2vDLEK44eexgVc77oyNs1kPE19a0ptgZrxOxvSIjtMhxK2r1JER5EFY-Z7r817lLCPyl9bcPJMy5ZPGPDbwDXGRHNcWfLEIkStRf6LyxL82yhVRL18ALdRuCUVLaRIk9Xh3-YS9CXBKS31372R9bPb4op-aWj3gbDDB-5xFIfBoU3lqjvHs91BdHk5ScaP0sHqwYyiJ3C_iWxm12WzYXUjFRDz6xuKkS5OvQEcs9_Zmg2Yc9Th36g-mop2gJCDtQRMgT3mtGG6uwlmZGsSiamsHeZJCQQwAasWf27nR5e381BPkcNHZR4isGDFu3ck0Xe_aboKwWOKvaCX0rVDK9awQV5PSh5brvp3a-TJaGQpapTibiL1P5VcdU4Irp-SkzKNIJfkZ-lPJGVhZvxFBMcngGJU7rDF5PbeHblRM0aD414xR8Hn514XziTQsZTQQlF9Z5nBylo1ln1XbXaHHTZVyQw_NhMt5w_PEgNmsu1iRFSB4awfKBt9V-oMwRLo_qKA-hKJLmbT0feyFsp4mRoCDFl6o_cIVeLneiflvDp9MTEQBeM7dbfoiQs1JVpXtb6pgJWi4f6y-VFuFQ_D371MdebCXdBElzPf9LPgLcJw5XcGc8zO2zsKXZLukxupIgaPjwuFc14mM23jWra6MSnaMKrBxgW9rU8ivfxVkLUBESQbHGrqovh1g0JBXAK6Gx-nlPazcZK2LfBNhlAHNTmJq7IdNbaQFlKWEoRL6l1-DyemaeVuido3YUNW4O8rDsUKiEX9VS9s15eIbtOJ3pays1_nMRWHXKF_mULi3ME4UP_iwYphTl_vAPaTqkWzXGEq23GfMOF-HkwC8jdmeo8dIC1F7O9QJ2F3Fh8XPQs7HbBRUNtcsgUEl1igtACz5I5hTl075jIoBolSSIaDiCfdj3tj0XSjXRnm0plHxdjOpxib2skKUscR8OUudaB48oRCE3pdQSjKubG_ZZNruQrVmcOW2MgZ-DNjEgyIO3CT_DO8F70Zcy7jXzKILi61iSABPh-3MP4qGmRU0cCf8HpkbnuD_8-ah029Z_9fi6ghLuoa-6FPgSx56G80hnD0s3l44ks3d_GAtDJu33eD_mA40cRndbOWDKqKH-2Ch0ZJXXXHBYB7R-Vuq6LyHBasXYD_spVlkO25nH_3ZIHd0fa5EGct-Wf3twtz2CQEBQwWsjZrMbsVSLkztvUn3lk2CDqoqoU8lm5-bM7SMHfSHsJEgQZK-lQWXHdQSjuXppZpMbinDp-fv55kE0ZFtcVPsRvam4LS3L4OjghtMf6uRrzWS1dFG0NZ8Na4-WiIjQwuGroz8X1ulx73UwJabrhGQvmA8BuhpofqYrCyN79C_R8YuwGHNEOXbgRXprZ4syE1mlr0CvR7txC2D_F_ItmE3QMLAmSmam27jeDqTgQhyTSgozASPmV151tLcxfRjIoSAzBUJw-W6UmnRICExZOP0Mw674P5KFzH6veckK21puh21iTiWJ6HZMtTa7GxM1xu_ArZAZmpxZ1cn2KiUaZ2UUcD-KykvfOmF97jF4pTuwcJmzoFqFdq_znZYBsDG_01cEqQ-kbBAafj8s6Q-WtGdzhqifpV6rlWpwVpx_NNloI-iUItx79nBiYnGuzTA5bUoihIMVFHGS_zP7hjssm8Bfq0hAIqrYHdV7VU_2s1RVFBESW5BzE1E55f3wslshXr_FgcHFy7Kr72rb5tk1j3ZgsfCUuuaYDA7LlqeevYzU_G1zNP4CH8Mvlo58V2M7lX6JT7664Yi6eTmw4rr8bmNgQyENT4915mGetg8c0mLNI25Gz5q4NKl3cxZkqaQv8cXZ6GKTeJxYaQn78d-UNaJGZ7oqJ1Qmr2zpmdcNnJxlx07knVy8UNVzfaCuevIFnSn8VIWB9_SQyQ5YNhHIC445FV62ZNh5KgiwU2o0S1ia8zbVbJk3yUm85_iSQdFZbhtrTrp9ss92sf2BRr121mlR7tV5fXssiovUjYstppcIzHUxmTHFHh8KUhS2kqhP60nouVeHobMOuuWW37Y92nnU-15mfcUT1z7dqp--Fm31QzysOn4B6tieEDRZpssea_CHVnwPQS1NfBpx3t62ru6cNfa3qfjoBQijaO_7mVWBk1-uw6JaX82U25mwOePwof26gWDu_G33cHvfSN909ToSqSUtXs4kXxvoSfTAwV2Bz3OjIrIvk3qnfUpJXCMLf3fQD9em1ze9V_8P5Tw36kU2_BgfJRyBOW5pCWkJZGNRpl8XnfzNtd-1j7qfal71G1IcQ2UhQEZ7l0wgtr5MsbE4VUMZMmMoHIl7E9gwRVxVH8Mz1J9PojKvYrySbX1AAp9_zxtnMX_BBJ6aqP7nCC9Ju25l6Lfc9NPXq8WybMDvHhFy-YOwwc0MJ3S6SqoXaxmhxrdcCNGZfwFqJxSOydlRifZ5zC3XDdCSHPw907QMI5_esmFMhWr6FEFBHHNT8YExPOeojpRWDMsHqyb6wwH707o4SPm0Z81pJ1Sm918BTn_15Sg9nLBGv_PBoJJfgea88RnD50F2V39bDWYkUnNK_nFpzh2Gn7IQwoEZJWnuQakG-kON3aTb4XoRwpdkjClZO9bhKA4DNX6gIWPWme_c2H3SXORUYsLJKC91vuJki-_Bjg-6SH3uzuKwoX02HjaScY6mXmHBHNJCHC400VqjKE-mjDEHSBLIFn5LW4mKRk4soaw1LRXhIR9QQbViKKsX6wg1tNhdOlhj8UGtDKKJuxgROD0bB3SWt8WOnhyrR9dX2xkCxrBL3LTWzxTDtQldsVw2MBn0YKYNirc_-GNaUiE4tG0VJqUquFLQ4ZZcPTPgHDySKi2TO8RkXXYNtHcMzCH6evONOYDOv1nD2p4uhIGifX6JzJm4zL4_zMli2NhWBKsRGc918zncLaISfvy0xActIhYeHSUIdlBEA5cX-xTtIV9K-58cq0IgmfPXq3VbEA7kQBK633PkJlcgUjGwttFkyF1D-1rvkwcRyNMmRHIe_tyPrkgIiUJAyQvIYrnHV4LtLyuVuTe8TaXa7NCSZ5L6jMWuGU7d4WL-lPufvMVsvC6VtMoo42z5NpdxUq99rwxCym6C6mUmf8i0h6jis6VleMWg-ryQRSoooAsoBWOfsdqSv5EU7a4PJ1U907Rt_OoLspquvq8wNsmmEmH1Q.B6wQyyEzI-KmP_w9UAMT0A'

Figure A.43

import json
from jwcrypto.common import base64url_decode

parts = encdata.split('.')
# get the first part of the token
jsondata = base64url_decode(parts[0])
data = json.loads(jsondata)
data

Figure A.44

{'alg': 'dir',
 'crit': ['kurl'],
 'cty': 'application/geo+json',
 'enc': 'A256GCM',
 'kid': '6a9e5727-34c6-4045-a42d-7125cb366d2a',
 'kurl': 'https://ogc.demo.secure-dimensions.de/kms/dek/6a9e5727-34c6-4045-a42d-7125cb366d2a'}

Figure A.45

# header contains the 'kid' which can be requested to the KMS.
kid = data['kid']
kid

Figure A.46

'6a9e5727-34c6-4045-a42d-7125cb366d2a'

Figure A.47

# header contains the 'kurl' which is the URL to retrieve the key with 'kid' from the KMS.
kurl = data['kurl']
kurl

Figure A.48

'https://ogc.demo.secure-dimensions.de/kms/dek/6a9e5727-34c6-4045-a42d-7125cb366d2a'

Figure A.49

A.4.3.  Get the key from KMS via de kid

See https://ogc.demo.secure-dimensions.de/kms/developers

response = requests.get( kurl ,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

data = json.loads(response.text)
data

Figure A.50

{'kid': '6a9e5727-34c6-4045-a42d-7125cb366d2a',
 'alg': 'A256GCM',
 'kty': 'oct',
 'k': 'UbFiy-2i3nzPkaUVEvkDF29FDoN7vRUjN5ACBvoohA0',
 'issuer': 'https://ogc.demo.secure-dimensions.de/pycsw',
 'expires': 1666366243,
 'issued_at': 1666365942,
 'aud': '4f9610ac-9d1f-3797-6a41-6b18f9852572',
 'sub': '4e7f5c63-0552-30f5-8b56-03e634ecd978'}

Figure A.51

A.4.4.  Decode the payload

import jwt
from jwcrypto import jwk, jwe

# create the DEK from the response obtained from the KMS.
dek = jwk.JWK.from_json(response.text)

registry = {
    'kurl': JWSEHeaderParameter(description='Key URL', mustprotect=True, supported=True, check_fn=None)
}

jwe_token = jwe.JWE(header_registry = registry )
jwe_token.deserialize(encdata)
jwe_token.decrypt(dek)

decrypted_payload = jwe_token.payload

data = json.loads(decrypted_payload)
jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

Figure A.52

{
  
"id": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001",
  
"type": "Feature",
  
"geometry": {
     
"type": "Polygon",
     
"coordinates": [
        
[
           
[
              
2.83,
              
51.18
           
],
           
[
              
2.83,
              
51.28
           
],
           
[
              
3.02,
              
51.28
           
],
           
[
              
3.02,
              
51.18
           
],
           
[
              
2.83,
              
51.18
           
]
        
]
     
]
  
},
  
"properties": {
     
"externalId": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001",
     
"datetime": "2022-06-30T14:16:24",
     
"start_datetime": "2022-03-07T14:02:00Z",
     
"end_datetime": "2022-03-07T14:06:00Z",
     
"recordUpdated": "2022-07-21T22:40:13Z",
     
"type": "dataset",
     
"created": "2019-05-22",
     
"updated": "2022-06-30T14:16:24",
     
"title": "Proba CHRIS Level 1A",
     
"description": "CHRIS acquires a set of up to five images of each target during\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\n                    classified as modes 1 to 5: \u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \u2022 MODE 2 WATER BANDS: Full\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \u2022\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\n                    distance 17m @ 556km \u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\n                    bands, nadir ground sampling distance 17m @ 556km \u2022 MODE 5 LAND CHANNELS: Half\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\n                    Proba-1 passes are systematically acquired according to the current acquisition\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\n                    users. Observation over a new specific area can be performed by submitting the\n                    request to add a new site to the acquisition plan.",
     
"associations": [
        
{
           
"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP",
           
"name": "Download",
           
"description": null,
           
"type": "WWW:DOWNLOAD",
           
"rel": "WWW:DOWNLOAD"
        
},
        
{
           
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG",
           
"name": "QUICKLOOK",
           
"description": null,
           
"type": null,
           
"rel": null
        
},
        
{
           
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg",
           
"name": "THUMBNAIL",
           
"description": null,
           
"type": null,
           
"rel": null
        
}
     
],
     
"extent": {
        
"spatial": {
           
"bbox": [
              
[
                 
2.83,
                 
51.18,
                 
3.02,
                 
51.28
              
]
           
],
           
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
        
}
     
}
  
},
  
"links": [
     
{
        
"rel": "self",
        
"type": "application/dcs+geo",
        
"title": "This document as DCS + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?key_challenge=123&f=dcs+geo",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose",
        
"title": "This document as JOSE + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?key_challenge=123&f=jose",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose;profile=jws",
        
"title": "This document as JWS",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jws",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/geo+json",
        
"title": "This document as GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=json",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "text/html",
        
"title": "This document as HTML",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=html",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "collection",
        
"type": "application/json",
        
"title": "Collection URL",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main",
        
"hreflang": "en-US"
     
}
  
],
  
"assets": {}
}

Figure A.53

show_on_map(data)

Figure A.54

Make this Notebook Trusted to load map: File → Trust Notebook

A.5.  D113 GET /items/{item-id} with DCS (JOSE)

Example: 3.2
> Access the OGC API-Records D113 /items/{item-id} with DCS (application/jose) and public key. See https://www.rfc-editor.org/rfc/rfc7515.html.

# Prepare client key pair for encryption/decryption (public and private)

cli_kid = "clikid"
ce_key = jwk.JWK(generate='RSA', kid=cli_kid, use="enc" )
ce_key.export(False, True)

Figure A.55

{'kty': 'RSA',
 'use': 'enc',
 'kid': 'clikid',
 'n': 'rLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ',
 'e': 'AQAB'}

Figure A.56

# Convert the public key into a comma-separated string to pass as query parameter (as per OpenAPI example)
ce_pk = ce_key.export(private_key=False, as_dict=True)

cli_public_key = ",".join(",".join([key, str(value)])
                     for key, value in ce_pk.items())
cli_public_key

Figure A.57

'kty,RSA,use,enc,kid,clikid,n,rLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ,e,AQAB'

Figure A.58

response = requests.get(endpoint_item + '?public_key=' + cli_public_key,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/jose', 'Authorization':  'Bearer ' + access_token})

response

Figure A.59

<Response [200]>

Figure A.60

A.5.1.  Get JOSE response

Catalogue response is an application/jose structure (RFC7515) encoded as a series of base64url-encoded values (some of which may be the empty string), each separated from the next by a single period (`.’) character. Next steps are the same as the application/dcs+geo decoding, but the decryption key is known by the client and does not need to be retrieved from the KMS with information obtained in the response.

encdata = response.text
encdata

Figure A.61

'eyJhbGciOiJSU0EtT0FFUCIsImN0eSI6ImFwcGxpY2F0aW9uL2dlbytqc29uIiwiZW5jIjoiQTEyOEdDTSIsImtpZCI6ImNsaWtpZCJ9.cMgGbydXjpDK2NasNt5_xhBI0CU1pJ7LkWPRtqGZ2rqlmHF7sEE18cpDcpmb0LvUiNrvwzqpzZ6_6SsGqusZWPk_i-X6eUBzDbuS_R35vjpZeaPdINQVCp39f4f5vZXXmOcA9fvLYPLA8HHNH2eNAEi8-5ZEVBcOoUKYN4NTK32xrsA6WZ0KEVV7Mhndn9XavQZe6gcuTrr3cyokt0m_P4imOuynuvqt02ZVAHGRpBwc48ItHEs18T2q953xl3yi8O_hNVwZxSgGfhLwIRTdOfYfpSkZpZotT6qplZyTT_SNVZqtyvlOfAYgQZc1BLbu5VomqbL2tuqxGkfszj7hWA.Co1isjTv7pCSgz2l.8YYNi1GSZmls7-EaVxR2tEFBaHFvJSDkFyxe6gqMD9nxbu4TWHMOf1CmAtUC8mSrb7uInenFgUa1l4SOB2_MJtW1oUZ_SPCZoQ-FciZ24zJ6gcxCV2JixFC3YZpcxnFm4vQ-LcPwffKwXTSqlP0xeCwL-x4aOxrDWME7GA5s9LAW-HcdWG4ZKbHspLBLjgG-eul642baBWnOEPhV4XoQ-kX4h1DoPj41KkXcXFBlojh9-YLYmjtK8_kYEnaL9htY6VbNHyqvmn6j5Q7P1FDEfL_he4PYgLGRx0sBHpqvvim2xfUMWnPm_E3UiZ3NKQojADiHbUyBQR05HesN4cS7wXF_VOPYz5ZdweBoSkCyGbe9fc1ruOFT7Sm9zuLjv04Oq0p27hyraxeILh_l8MLCQnJXbzn7jGbqHtescQTwM4ewBAAOSP3kb6u26wNYGq7GDYnww9DBhb05QUhtXR0ISRPDjv6KVxcgWSC0R8CR4BT4mghUfFNBsT7LtPqRnWgFCrOfnLHM8Ldhn9N_FpyI6mLfQEQa6kKvJm0EeZ3r4HWCrWCtFGJ-uqc_oRtnKJh5xWecql0VPbcC3xRJAB2LYNPNyqrl54nEabf0XjleInV6mcVzhn2EBQt_Z9lWp5JcQU3z945oxGP9FfiXV7lTLvwW5XsGNTYx0qBqTJkCaqwxPaj_en8ojRJI2muk2NPnXEOZZkP_Ds_kVG2SWberwReMGqtMv5i28IrG1gSQO46365dCc-R43B7cAw4LvR9TTL1mp1WVBe0E8ppW19OAuktaGOHDM1k0H77cGQsJOt_yUANsMyaR9FyfN1shY0LHqj6nA03XwLr-vz9PRn-PFJCUATGjbR1CfIfI851gxNwfeCgdXlOs9bFxd41FmkgHR1auTkCNuGGfkXt7-VPBVtyFFDNWcNUEyfL1w95i6iRWFtxOQxNToFtVPmRhT9p31gcgBNsLy33p0RdqIcAElfG5BKDJ7P31tJOoWtVywhibvzXJ2Ojye35QtDpyMvvHZrm2oGyCSHJR4aGE5uiHicQZiTBO3JVvWKZo8ocTizkImrttPY-0xe2e5TAvSiorZPzlXxlIUiDlhc-6NUs_FykQUKGA-IeCM_RsG6qpB52bhO0nfECV1YC6YuKkQbWihzGcOO4Ze5mWKdvfmNGU5AVbqDtbW3S1mkAc6WA038p0EiUM4L3THtUWw2ea4EP9OVKex-3aqKboERmyGAYNUn7gR27N-MDlYUxafZWy1nP5Sw_CgdWCtPMGkvUFFKrMBCN84gsmuwreQJGF-yiDBruOsL0nYKUyNgEeCrA3tnP9SVVHDvv-ZDC1svuxbZb_9O9WAX6B7sdsZsDV5dQ-vph49IPhys6IcNV-doC9ettkuTH7RO2x7ZSop7uasGSP9tVljXr0amC0uxCB5oudxLAHm_MacH9XiVD6pnY3aAdRoGaBWdNVqgHJnKympn1z2ZsRnHT7JnRfSrfXHVV0ja4K0B6w0GHL3tIRicRZXpy68Y4zqY3ore2XWeN8o5-RNvlYC0mbD1OdkS4Jokor14ikOtFvUxU8ti01VSkZPKDNUGSJ6391VsG5HRfh54mZr1gnAc0jRWgz7TWH1LytZwwqfxIFhWzqGCQCNWgI8VC4y8VRhKXyxoO5BsHn_LG5i6mUAEfQPVj0LiKJX1qUTtFux1n01aDRXp0gEca1QLknxffBMlwEL0_d_q0BD4AwXB8e7KW56s5PkY2HdqLnKmrA_e3-gwFDewcq-463V0ah0zRfARWXBjo8dsL6ezuuoBLSvurpvPOBWmMngmouqHZJ6jq2f6GM3oWyuwqGUJefeGjiP7cMEfsEK48Z2E1YJiEpA5Mvo-gbYrPXtJxzlQj6x6em95KQbvg_pFbbakr9qMjFCpd7pKk3YLlBYHma-61fzR9CDS-pJps_oEm1ApE8MLbDJgD_UtHyBbz2tHQOCtjFR7BSoajgGq1p8wZ83_a4acyzYjgXmZnls_ZuDrplw1G2Si_7kq4zllepo9_dwE-eFKtZGlUqeofGq6eHS61ndXBuoGwjsGFBShmfNPNqp0hDcAO_jShiLclB8b9uM0e6VE5faJHsZyD1AzBzbi1F46U9m96eiwWjUadHgtKOQ1b27gATLQ1ksuaWdWbHTC-O4VTINVGaZLRYEhSouLJfDGtQ-FpaRA76TbL1qCNhdQ03yYqn4DTgQ8W-QkGzTaz4tVODfqIRPouanmIFKjvhkgAJcds3OvllOaBCEkO-mS6HNawji81yz78mtIJ03jtNm9zXkwxxs7KTJ-GPDtb_2oaIDKAT1cqPixKyD1227OWReF4RSOtKKxw6hIO0mzt-LUIeOCoA5xK2YNABOi7-kqdS4vPDIF-t-WMgrNQf-MT9K9uSqZvUhcyNzhnEuSRu5pUMUjkB-gvKq5EwLjx_JsdovrwqouPIR2XV9iOczk3Pzmv1zsQuug-5KjD7_NGfWzQz8BzG1DfrhPB0y0W8y__wLNd1Q1Hc--2SsV82OygqWFz1RwwQ3pMfHGsmm74cbhGtMKQe4NeasukvJDtDdeezVxROPAWFDS4G3aq8JJirb_NByDSv9skKEaY8fRopfmDTT06seWM7N-SD_VTbEK13lJQKXZiN9xVRNJrQmPmWP3pXAQH65oFMP9L4xlqcgBQrujS1P9bZ2rM2FB9cfz4iMOZwWaeSyJ-cx8f7F9pm9rnH9-zrcrqomn-OvqRlFMT9Ih675k1C-rUd3P662OO6Hr_RyQfk35CMHZmBt-uu8bHk6xzpstoixqv6SfAe9R_EhgEdavRl4OCxHv-TFT-HctOF12ySX1LFrh6T9nKDiJawFGntyVD1Vwfaoek433_sXsH6Dd5YJet5TQlWyAGxdwmvOEm9bDXhvNgrUMXeFDDTheDS9Vb5s265kFb41Su0Cw98DB-MlueChFzJCo-RmAas6HUBl0HDVguoYurRfYraSM8xRDs6uJu4woeUs5WIz8XdR5DvD0mZ5orAuL97a3zzGvSID5ttPbDdVcUDpy6ySkpERN5wrOIVQkCDxXjzQW7sB9VWeZlviJ-nVBEmDUQjEqtjmOd9oGnOyEQT3WsKvrhk2tDxHC1jFx6n6sgtKK77EJwCffwzLwATLmOnVLEbpGVfLgVQ1h8473whRAbv9eUGkVk16Kh0OxMnSAN4iMJCjLr_9aPqGyqipVaxfAAgiF5zgEOPW7ShQoYt5cUqfInYYIsPfS6M7hWcu3D0VMr4j7bFgU1z1iSvcUyKT1jR-cHApGZFE_aGvsGKdFpomye1ufbnP0z4ieoUbzgka90MTieFON3SuK_QFd1rXuuBfeVGlEDdZY0dO1-a_zducQgfzJA3Nd49dJu2ORtfnvBoYmJtRMAe-7J2mEzPbLpB14rIldHLzVfqXG-GNd934Gl21IWV-oez1XilQejeGPHOTlI9puezxQE-rcucah7wN1nB4yICb1W2iYsXMYj28zkQwWwdlN4gbdQjmAHB_k1I7Owta7jphFrqg9owbIXRAWaMng4TS_HIlH9Bke9W81geLkmQnGqFL-J1qr1XtVGE3xsQW2GTOOlH0YzY_ci5rSSr9vF39iUrrB75QUxExTFPLDsZOBxDlQ__SMDWHBfx051tymzeMasY3Cf0_EiTyDHUu-Mgct9ZSfLljB3BH5Ij3cekFgHK3mVjwcn_3RQfWNdrRjAM7tb8BsQQ-z0U8GvC7TN6nbonfwDYV6dgAWqDFhEhxujnfZuIwja_CLBzvDpGPk6Qa6U3_DpNmw4NmsE8TTY9RB8__CXwPHoL6rAASKNOrQuKuGqMVnUGt_3zaZ0VV89XaIntuFszSUDrp-82XxmzjBJMbV7GVyti3bwP0XM3_ltqfKIh-mhAIUXJPIqxurdqFWbwwqAbo9qr2D0nTCZRW05Stzml7etgmcQFYTtKOFUAx31qjhNvZa7Q26knMut8B8yJY7xaj9SSpVAlR6KFWEnEtmJNcAnDfSorPPOrZ8PGWNMzV_ZjKSaS5OEHkjftj9flox5zShioPxfIw2UOktWNZXlphezOW_YkFHW-3td1990aUv46dEM6kfLpHM3L8KqB2vz3dWq9wUqQVJFcdIMgHvPlEz84yV0-LGj9pORqXFeRET7EFCl5g5m49GpqBW4vdsneYphnvqY6pe-QIk5zRXAnVlZo1RlXIhM0oBynJD69jZ7ia7rb-JNZh7pRfP1XHeTanyegFqVnLrwAV3Y3NZDhl_NFlFgSBWOhLt2XISEez1SAlk6tm_k4jhVXQX4QRWmUpaSzTNzXTv3AEtJKeYK78yHHDNe1d6ks1XBELkXzlOWlfA-hHmEm-csW0HRyqW_RV_VAASN_H1Q6Bqrq2JOUS6KdWmOFRAKq6rKwDyr9CJMPWA4uVCY0I06mBpqF0M1ClvPzLkAy2TjEJQv2VEim-ctaTicDEt2ITTbIHvKTd9vuJc32mkHGkPSqM7cETeo36tZ5oOZWoSuHXj_ZMoResjZ-dWQVUKdJRkAwXKPcxc7ZpDMGkK2StNizZys3k0Yla3XSZ4ahYU-yKqmiq32MC-G8CPr35LR6CgnkhTQtRGgO-H2h-Pbf1VY-K5E7Mgx1mLjGfeIHLmILoCLBeRFtio9UUJ31MLUza5EJOAZ8DecoEp34RUzckfmI1zKrLVVbQFIcfK0IeLuxrokemJk_8a5-DoUx1sgMzTzjBIejnjv49L-hkT5X5ARB1Svq6YP2nKcg1zQi4z9R7U-IGTd0pCnYSviKatuuwZB0NGKv3N7VM7hl0UOWvFB0zBoNLULvGc1xBW6heEjtnoyG5IwhKgd6VF4Zr0_9OzXtyyM6UyjUrSVmeHLazpLoh6YDEXUK5dK5fcpKHYWDL9GZZeUhXxs-pv3nOuyXNCXuFUI7kKXaAgwaLOZIThP7qMZ8UmojEeS3SMBFS3wEb8UU9ugcmLwEU9tO-cuQwoQ8WAYyhBxFwha3F66_blZa244BN-5cF_LmOrjtzLbK6GLIhSzcSraYgPPmdd3nR0iwJRN4fLg0bwnN4_LrilHKsf8dK3JvUN7qRblRGLAQV-ASyt43slkknT1r90x49dnRIbyRrL23Kt3xG0ZGR3sLg8Bsiz8XilyiadTEi9eJIetbIH7Xznt4jmFyL1SQN-1ujVISru-YqaB7tvzIIYAT-ZegTVwXrQSgrJakg05UA5NNGc3Xuzetoi6P1gtklq2HnNKFzcfctMV7Ps36_y70omMYBKYDYD3yuKMfzkLgVZDvbRQeADQYWEpIi_l58y2XYAGjHBJPNN7NToKJ3E-B0-bUnBw-W9AgHndIjQFJ8lBn3zP3CyGg603lcvjfz-avCr2SAZpq-O_j7LvMWd_gbFJ0eapkCRE2TnbCfERX-58ZpJ0LivJxEbi6OgkG_a1p76QpClFocuB9dDh2C3_sAaTKIA1T44aufJJ_q7NAB4d03KbNmDXebq7yDrkJOufRqYK5DafR6UjEwWF2Qekpx24XqslNTwzd_rtE1ZwpmGN6AEKF0VxU4ws97GPqAu89w9DSX0sXEIW9hGj5RxxmR106Ne4B8q_LF9t9VP4Al00_0jVOTsbfTjLQyj8w2BVDwN8hqxyanvOoSMDMH6R_CTmlA6UQv0GukohZ5fC82xdWxjVBm-xYHy9LeLMBQrpymlOnCo08fbvAFC5s2gNWXdA6n0Ub3FL32N1bJh8HIJQKOaPvSksuMWRORg78zqMIta_U2O5eInSUHBuj7ehdmL_fxltqkMKYuzlox9L7rNYBWad8OTtARcsMDvUNrzoTq-0EKkTiO48fgEKlAYUbtrUOnJ_CKIPpaYiK6tuJ5O_I4iRwSZ_ZGxpGd8hKBxlyCYZt0pVhhJSQYjIM60Mq5VO_rN9cyTtOlCzDHRcfU43DO8ut1vesjoQFtKGjcK9j6cuvB8S2cL-MwIXi6Gdea7e89FwY9-1xg-rhb3t-MccX67zojYcOl3HQ3hg86E43RAvHRZ3H1Bf_m0DUc8iom3_abLa3xpP5nSmrKyh2gkBFgDK0UifV1FhBoEre6bmrrOQTedw2q8HZ2olS4t5aADLBIpWsMKBmlcTrhAVMvKV_QUpECzY7xTeYK-CMkN1IgMKFwtG3QjrbEHcO958edS62ho5STTjo6JBIJry7R6o1FytiASbx8duOyJdEzg1yhQqI8I1RsGROBo1zucgyky6RukPFN1gkK7OL_50TBnm9W1bzaaYPyn8c76rl3KMx5WkEZJdPdZHw3qJXeDKhtIX7rPnAeZb_0bUZlwJCyoa7qjyzkEEGCiSyNh_ge9znS9eLbbhRYxQm42D6XbVWzgGR4NW-3Ylwaz6Fzm0JklGR1n_Z-7bB7tPlq91jdVFJ9mqik_0noAuOdDIqPLKIjES9_gS8KHDnG850sn6s45RglVloq6UwRY7eRMRs22WjOJ4qaR3-hESNqas3S5Une8pEcV5l-uN7DaQwXjEl8Eyy8yAwMdPvAKdIf4LYAZslCCE9yGNh5CZuziX0R67ZA6tYE16aNUMnUW2I-5dGl3lvlb-ZuaFHFRFxgv-Lg83uJy9cj_82xhFpGziImZaRHIU0MdllFoIN5jn4mDgz5AWw6y-inQA56HE7qLl58s7CCa4LFfFKwwATKfKe9rFCc8trWu7obwA_VD3AXscBE2elOfQO2L-4qLGU3aTg4sD1aSVtAbvaEXMGh1msRJR3-oDBXS3x_onA_MSQqN9jVX3AH06owZgfY1NzpepKPRPTYvGIR1UjhGuwzRqhPGHPXsW8QqgMMxAw6tOKQ5uEY5VIfX1K9O8Wobo9WvzIlrh8EDXc4Ns6bYK2PmFqo7KUBcObXKSJaSULGyusE_WWCzu4MIeFRkLfxrGvyltATVbPJw64YDYI2YQTDIvWB9rmUgaYieOHS7DFChqK49fZa1TQPHOJcuPNxZig9EC8Wzz83HjQRHC9K5Dn_0kxS_KaTLpBfkxyvux3n171mPCZJgaJaIthdCIiOMS10j-rHaVndSr4UhDckQYy88vMzGx8Eo64zgTsSA4d3FN_x84pWFoh7EN8rXniT_0kw0t1e6lGTzRPDpO-NijZNFMXKDDMTnO6EziGaRpbEKXTwHrgAxi1CMo_-fB_-TT_f1I3rA1Q1cFESICasYDvV3fDO_qOGY-mgyxcsrxhBJOidn_PSjYV8MBSUADrdzXL9VEn5FNt88cky9OBlYUqTNVFaXEf7Uaqnba1fTNF2fRVtp9gr4kk3ZlyeAWDO6Npqqr-mEYxmULfAVak6Vfv4waT-QS4mQs0wsOYgFAzavBqkePGXdZgTyFiGjobnlEVifV4XUVz0pNKiG5FaVXu0kHdqmPxK4jBI3UZjBptuwTwNUeYYSmddKsSYWaaI2C4i4av83fFBnBfLynfma5y0XaG_f1ow_G4X0PUt-hGq6BtFXbivpAAfEk79qrNVX3jgUH6t482ueL4ZPMePJ5mr4zH8e7RizyKzBEAg_Xx_ml5wbyf3fiLPiiCcRRF3GIYQ8-pL6foKfqAKliZgpkdR9hSKx7SHG1QWK4SLrTOe9PsI_xk1gkjbRj0HrP1UINWhXyWheHYfkBj4UcTe3Tbeocae6P8Mwsgw-TCWlBBBo0jZeRYwSFl9tAKt2ZB0iWu0bbdPH2C0IQJ32skrWrX_ppSxGiFMk9rP-jytP44Axlzd4inayKncv-_CTqiDxHvQOs_-SqCYFeUsIA3VR80CSMvyIDwjp4TkpVC3dAJJejEN9Bqm4fJnIRIoXHeAYExJVR_IhrJGd_2akTfC8lSSzPN2FCWswsr7gtxO8L4XBiSA1fqpKjJFXIOVauYp-btNzC4kMG88101WKjwLHQHWUxnFWMcVm5Vk1QSFkadP3b8v2GsALvBcoBK1TaZCrd7xegBYCeJ-UqpWRZieurGPTl2BKKrR_S0wwg-KmWBJdo3fPZ-6R4vHwusTRYlEUbZMtJp6Axm1gYTgxTOp80v6KxWeQS7CRTrrBLBSBRD9sg6VFdWlL7tc0g3qh4qXe70JTqpmJTNpXaLFVfAlHLzsOcA6wz7ha0RQoSsrp8VqoiS7d4DGbhL_1a-pC4H2tU7jdMMIqcD7Hf_mjr87agcqVHE81_-YtxtDAvN9GcSTpTnrQU5UXjLZFA0xE8ONQvFg6oCm1nYfnDS7eIHnGqUFqxQIXOWT-Yaet2vyepb08DWr7k1dOEWPTwSgbUTLDy6w0vc_9GxVaMJTH9ps09e36M-04gq5jzP5I2_aC3Ndf8nnFEBQ101oivTEYf9WoCvOOVvwTNsyTft8tc2hhNwvP1QVzXNuMZsbj7n91WEC2odID8Gqw3VMNmOFmf6XCHDY1OZkZl87dRJ1_P4bybPw0TucLQklJ634DXIwD4--BTfveifHBEDyQVjJS3Tl32OpWJYDyXlTNYjLb_WEsarb9RmaKG7lksPZyOHSRauBpVgBw82Ix5v32aeoXotaPIFZQC58unzZInbKyHzIt5qfNzSEYP29_63oRIl6ACY.kJK74b1pPOLcuYpIDK4mOQ'

Figure A.62

Extract the header information. This info is not further used.

import json
from jwcrypto.common import base64url_decode

parts = encdata.split('.')
jsondata = base64url_decode(parts[0])
data = json.loads(jsondata)
data

Figure A.63

{'alg': 'RSA-OAEP',
 'cty': 'application/geo+json',
 'enc': 'A128GCM',
 'kid': 'clikid'}

Figure A.64

A.5.2.  Decode the payload

Use as `dek’ the private key of the client key pair used for encryption/decryption (ce_key)

# private key needed to decrypt the content
dek_str = ce_key.export(private_key=True, as_dict=False)
dek = jwk.JWK.from_json(dek_str)
dek.export()

Figure A.65

'{"d":"C15sP_l9yqYvvO-kyeIPMFHHeifHUaNwKg3ko2pcBdoUUGtbD8Fqcn7XXcFaW8HSkdoHp6ta1oKDj3JMxXFefQlLtYKg5Z0jqvEnp6XLnGiqEzj6ulCkoqfkKYYAHmtvhDedkgG8dQQHOMPRsOKjz2g3kHaCbttoswKcSq3rQHd7D_VxEGKZWQa2---cK1YmZBa_w-aNZ8-E15awJz7nIFn0c0COKUERmoF2tscN1_0r1JYN7UxUkEA3sXoyj0dmDK5sMlbmmBeUTSeuvA885C5m3GwIeI1ZElCvVjDd9AMGTSGK1QMydyzUs7F3LJI9942Mxw1iKlXFxsbkjVqn8Q","dp":"Yj83etJoO1KW8V8i23ml0SGb7kk0vtCuGRcN9nl5rQB5HIiI4c9zX-GD4eXAM-24RqIlTOBX6XmP5l91IOw9QAbHtelLcWGAfTtOQkPAY7v3TlZJNYacQDUUMbdn-Jd_85wh9VOpw8eyvhzyjCzniNz8buUKPbVOOjkI2X8FG8c","dq":"2N608ZQpomUpjVbI78NUeSrraz6pTOU70sB9xNjMFYqb_wuo3TaW319PpWtKm5F_lHfjgEvK644FlaU1TJmkAbwOoZuRG2ve4tMcdx2A_e-GAoZMhCi98QTd0gJsg8O9gLbujLa4a421Oes1rTBlogGrD_6UFRzdzPJm_3e9F9U","e":"AQAB","kid":"clikid","kty":"RSA","n":"rLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ","p":"t-BuJNDnlmUnPIax1K4msbDGJj5TAZjLMWC4riq13YYOyidizp5QuGIbu43hUmJUtGrabEi0JlkoOwHvBvolNq1dZlIyem62ezawGQvxdmZjG0X7ewfx9Go2mjWwEH045Je5TR5Aoy-xFigVECj3nOZEtJX-zndpvw-HTbvtRpc","q":"8G8P6XNxL_gnFx5H5jVAEbxObZu0jwrj6VxkQDm49BFdH8JdxTAYn6urhYIeJ0mtaj65eO8HfTgwugVLzWERrMQOpQplhcbl2JmczcyjrXGBVGewJ3LdnScilFVS9UUULIm127t1vfD8HAeV4mM3zCIujXrKZPEtCZ-eGf7b8QM","qi":"McWFm-FqXLIwI7t8Q8okkLc8K6IkVk94XwCjO9SrZydrEnDbOgpj8CHcElkdALTCtt-j7bCKPwdMb9Iis0TkjnUavQz_WNSyaS1HUE394DjYawb1lz042PbczfQTGkoA6mmT-ScOb8tTOn01mUJ1qEj-J-HkLvqrMy3r9YryZCs","use":"enc"}'

Figure A.66

# Decrypt the payload with the dek (private key of the client)

jwe_token = jwe.JWE()
jwe_token.deserialize(encdata)
jwe_token.decrypt(dek)

decrypted_payload = jwe_token.payload

data = json.loads(decrypted_payload)
jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

# jwe_token.header

Figure A.67

{
  
"id": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001",
  
"type": "Feature",
  
"geometry": {
     
"type": "Polygon",
     
"coordinates": [
        
[
           
[
              
2.83,
              
51.18
           
],
           
[
              
2.83,
              
51.28
           
],
           
[
              
3.02,
              
51.28
           
],
           
[
              
3.02,
              
51.18
           
],
           
[
              
2.83,
              
51.18
           
]
        
]
     
]
  
},
  
"properties": {
     
"externalId": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001",
     
"datetime": "2022-06-30T14:16:24",
     
"start_datetime": "2022-03-07T14:02:00Z",
     
"end_datetime": "2022-03-07T14:06:00Z",
     
"recordUpdated": "2022-07-21T22:40:13Z",
     
"type": "dataset",
     
"created": "2019-05-22",
     
"updated": "2022-06-30T14:16:24",
     
"title": "Proba CHRIS Level 1A",
     
"description": "CHRIS acquires a set of up to five images of each target during\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\n                    classified as modes 1 to 5: \u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \u2022 MODE 2 WATER BANDS: Full\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \u2022\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\n                    distance 17m @ 556km \u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\n                    bands, nadir ground sampling distance 17m @ 556km \u2022 MODE 5 LAND CHANNELS: Half\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\n                    Proba-1 passes are systematically acquired according to the current acquisition\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\n                    users. Observation over a new specific area can be performed by submitting the\n                    request to add a new site to the acquisition plan.",
     
"associations": [
        
{
           
"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP",
           
"name": "Download",
           
"description": null,
           
"type": "WWW:DOWNLOAD",
           
"rel": "WWW:DOWNLOAD"
        
},
        
{
           
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG",
           
"name": "QUICKLOOK",
           
"description": null,
           
"type": null,
           
"rel": null
        
},
        
{
           
"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg",
           
"name": "THUMBNAIL",
           
"description": null,
           
"type": null,
           
"rel": null
        
}
     
],
     
"extent": {
        
"spatial": {
           
"bbox": [
              
[
                 
2.83,
                 
51.18,
                 
3.02,
                 
51.28
              
]
           
],
           
"crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
        
}
     
}
  
},
  
"links": [
     
{
        
"rel": "alternate",
        
"type": "application/dcs+geo",
        
"title": "This document as DCS + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?public_key=kty%2CRSA%2Cuse%2Cenc%2Ckid%2Cclikid%2Cn%2CrLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ%2Ce%2CAQAB&f=dcs+geo",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "self",
        
"type": "application/jose",
        
"title": "This document as JOSE + GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?public_key=kty%2CRSA%2Cuse%2Cenc%2Ckid%2Cclikid%2Cn%2CrLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ%2Ce%2CAQAB&f=jose",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/jose;profile=jws",
        
"title": "This document as JWS",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?public_key=kty%2CRSA%2Cuse%2Cenc%2Ckid%2Cclikid%2Cn%2CrLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ%2Ce%2CAQAB&f=jws",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "application/geo+json",
        
"title": "This document as GeoJSON",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?public_key=kty%2CRSA%2Cuse%2Cenc%2Ckid%2Cclikid%2Cn%2CrLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ%2Ce%2CAQAB&f=json",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "alternate",
        
"type": "text/html",
        
"title": "This document as HTML",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?public_key=kty%2CRSA%2Cuse%2Cenc%2Ckid%2Cclikid%2Cn%2CrLItABpzNyhZDBFhi1kRX1PdlMVeT1d_Tik4bFwOcW7foc1R4O-oswjMGrhgSRDAj-n4B_anrQ6Z0hzr58aC0yEI_ueNzdnpOECFoA5vHPjunqHv9gqqa1vIQq4GDbEsjYA5iJ828UQVpTrdY7RUC-qT9B0Ib4TW2HcCvBuxrOh4kiswLFrfEtS2QJcYh4tScMFzZdIY985s2sDTf0qxdU7c4h84J_y292mfce-0egMzamnYOGOZfcoGXCtDC-pB6TbWGWtLAhfpkwRc1qiQUqcMru8X896eIIYjUjQdKnVc5nfwa0cUy8KlC29m0zAVQwuzUJHsnZuuCgqXyGj6xQ%2Ce%2CAQAB&f=html",
        
"hreflang": "en-US"
     
},
     
{
        
"rel": "collection",
        
"type": "application/json",
        
"title": "Collection URL",
        
"href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main",
        
"hreflang": "en-US"
     
}
  
],
  
"assets": {}
}

Figure A.68

A.6.  D113 POST /items without DCS

Example: 3.3
> Insert records to OGC API-Records D113 /items without DCS

# Get an ISO19139 (dataset) record from FedEO (EOVOC) to insert in the OGC API-Records server.

response = requests.get('https://eovoc.spacebel.be/collections/datasets/items/KO2_OTPF_KO2_MSC_2F_20091107T041750_20091107T041750_017498_E082_N028?httpAccept=application/vnd.iso.19139%2Bxml', verify=True,
    headers={'Accept': 'application/xml'})

# xmlstr = minidom.parseString(response.text).toprettyxml(indent='  ',newl='')
# md("```xml\n" + xmlstr + "\n```\n")

response = requests.post(endpoint_items, data = response.text,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Content-Type': 'application/xml', 'Authorization':  'Bearer ' + access_token})

response.headers

Figure A.69

{'Server': 'nginx/1.23.1', 'Date': 'Fri, 21 Oct 2022 15:25:49 GMT', 'Content-Type': 'application/json', 'Content-Length': '2', 'Connection': 'keep-alive', 'Host': 'ogc.demo.secure-dimensions.de', 'User-Agent': 'python-requests/2.26.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'application/json', 'Authorization': 'Bearer 4e6e701e0eb6a7d13e76b33da136fa07a2c4d7fc', 'Location': 'https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/KO2_OTPF_KO2_MSC_2F_20091107T041750_20091107T041750_017498_E082_N028'}

Figure A.70

# Get an ISO19139 (service) record from FedEO (EOVOC) to insert in the OGC API-Records server.

response = requests.get('https://eovoc.spacebel.be/collections/services/items/eo-pdgs-landsat-datacube?httpAccept=application/vnd.iso.19139%2Bxml', verify=True,
    headers={'Accept': 'application/xml'})

# xmlstr = minidom.parseString(response.text).toprettyxml(indent='  ',newl='')
# md("```xml\n" + xmlstr + "\n```\n")

response = requests.post(endpoint_items, data = response.text,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Content-Type': 'application/xml', 'Authorization':  'Bearer ' + access_token})

response.headers

Figure A.71

{'Server': 'nginx/1.23.1', 'Date': 'Fri, 21 Oct 2022 15:25:49 GMT', 'Content-Type': 'application/json', 'Content-Length': '2', 'Connection': 'keep-alive', 'Host': 'ogc.demo.secure-dimensions.de', 'User-Agent': 'python-requests/2.26.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'application/json', 'Authorization': 'Bearer 4e6e701e0eb6a7d13e76b33da136fa07a2c4d7fc', 'Location': 'https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/eo-pdgs-landsat-datacube'}

Figure A.72

# Delete the record that was just inserted.  204 response means deletion was successful.

response = requests.delete(endpoint_items + '/KO2_OTPF_KO2_MSC_2F_20091107T041750_20091107T041750_017498_E082_N028',
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response

Figure A.73

<Response [405]>

Figure A.74

A.7.  D113 POST /items with DCS (JOSE)

Example: 3.4
> Insert records to OGC API-Records D113 /items with DCS (application/jose) and public key.

As a first step, obtain the public key of the Catalog via https://ogc.demo.secure-dimensions.de/.well-known/jwks.json.

# Get the keyset published by the catalogue server from its well-known location.

response = requests.get('https://ogc.demo.secure-dimensions.de/.well-known/jwks.json', verify=True,
    headers={'Accept': 'application/json'})

response.text

Figure A.75

'{"keys":[{"kid":"catalog-sign-key","kty":"RSA","n":"loOcM6QC6jUB6wnMM7S5px2OPkLbuycsA6qqJoFWPkXyFFx5Z6CJNOc-7li4WBprIAX65Sh6aOq3bBZ8FP3v7R7mZOo7e5fckvMTPOAzizkjXQuN8ZZoQta6xu9ryZoTkD2bOK11buLcc_ZtZt3pRBkgA_ZHZ7LJawhnkMGq_hpSMmDxkDoUHsJ5PLH1yATPhquQwdUWajUZJMs4S7Ns0LgCDoj0zeixq5K6lip4Mh6hSoRep8aB4UwshdV2VUbpBP-Tq6MF_DzjeOEgIlEnILu2E6JN83Dz_sjDEdrC5qNjEDLMnLJTzsrnOcdD3FrXiDTolXjmEjnq-mAfjL3IvQ","e":"AQAB","use":"sig"},{"kid":"catalog-wrap-key","kty":"RSA","n":"utfDC-oXhPJVBn2KY-Lus_H6zn_lx5K6UNHySSXaAeu1cI1Q5UM782pvWI1iSxrq0s6a1a2faGocfR5XP7hugmQaQaTRHVTRL7L1cvu4oCLDm5DzI0CN_um6BH2zUW_MUBqpJuumgHEH17sMumg4jeH7x3oeW0xM7g-NzaCiQF5IEDMVHC9HGytpJcmCAev0vHR80oe7hSncJwbaa_Gryh3tH6YPcml-seGCJHPrLBIMVeTaSr-65gV050VZs2vF4W0bq_1AdObq1L1FISkHsayay0kleC4hq09uY5WqDkAHIIAxsj2R-weAE3M2UunIyKLFdXghnktlb9UKJavi_Q","e":"AQAB","use":"enc","key_ops":"wrapKey"},{"kid":"893ef3c8-c249-47a2-91e2-001a0b201647","kty":"RSA","n":"nhM1yyeJzcopJo79Cy_0jYbdhOL7XNzuYb2zi3HyTeQaNKwAzvt1c1MNMlm3Mt39kcB_mw5ehBZS1UZXGDWGV2BH5WZhyvTufxONizUlb65M5NHRMIKbmeDEYgyegKke6aaNaOl4QfSI6sd7JH6Zq_RtFBb85evfm74poRuV_JnS7u8j-kKrXUTgHNhwxHa8xuyz19o8506uWdDrYta53NYiuWdZ_So2Mzi3eK26o8rO3IX9Wk6nIWTYKmYetwYps0KOi7Q8hiH1RknrLvnNFT-z7eK2SZ3jycZCbDmD15KAasm5HQAlP3tOWJvq9_w3HiZakHZlNDwGbgCT1l_1pQ","e":"AQAB"}]}'

Figure A.76

import jwt
from jwcrypto import jwk, jwe

# Get the keyset from the catalog server (receiver)
server_keyset = jwk.JWKSet.from_json(response.text)
server_keyset

Figure A.77

{"keys":["{\"kid\":\"catalog-wrap-key\",\"thumbprint\":\"cqHuddqPaJd1vpyf7HBee_qR98eabtEIvpuFgnQlO4s\"}","{\"kid\":\"catalog-sign-key\",\"thumbprint\":\"uwatboW3aEXg3z0g1Ci6jyQzze5ZbpvYC_ahbTnwXs8\"}","{\"kid\":\"893ef3c8-c249-47a2-91e2-001a0b201647\",\"thumbprint\":\"ygIxjy7LMfiUVhDwEX_esDpGK8dsw3SnJgkF8yT4B6M\"}"]}

Figure A.78

se_key_kid = 'catalog-wrap-key'
# Get the keypair for encryption by the catalog from the keyset via its 'kid' as there may be multiple.
se_key = server_keyset.get_key(kid=se_key_kid)
# From the pair, get the public key.
se_key.export(private_key=False, as_dict=True)

Figure A.79

{'kty': 'RSA',
 'use': 'enc',
 'key_ops': 'wrapKey',
 'kid': 'catalog-wrap-key',
 'n': 'utfDC-oXhPJVBn2KY-Lus_H6zn_lx5K6UNHySSXaAeu1cI1Q5UM782pvWI1iSxrq0s6a1a2faGocfR5XP7hugmQaQaTRHVTRL7L1cvu4oCLDm5DzI0CN_um6BH2zUW_MUBqpJuumgHEH17sMumg4jeH7x3oeW0xM7g-NzaCiQF5IEDMVHC9HGytpJcmCAev0vHR80oe7hSncJwbaa_Gryh3tH6YPcml-seGCJHPrLBIMVeTaSr-65gV050VZs2vF4W0bq_1AdObq1L1FISkHsayay0kleC4hq09uY5WqDkAHIIAxsj2R-weAE3M2UunIyKLFdXghnktlb9UKJavi_Q',
 'e': 'AQAB'}

Figure A.80

# Get an ISO19139 (dataset) record from FedEO (EOVOC) to insert in the OGC API-Records server.
# You can use any /datasets/items URL available on EOVOC, for example found via the STAC Browser at https://stacindex.org/catalogs/fedeo-clearinghouse#/.

# response = requests.get('https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/vnd.iso.19139%2Bxml', verify=True,
#    headers={'Accept': 'application/xml'})

# response = requests.get('https://eovoc.spacebel.be/collections/datasets/items/ASA_IMP_1PNESA20030910_100809_000000152019_00423_07992_0000?httpAccept=application/vnd.iso.19139%2Bxml', verify=True,
#    headers={'Accept': 'application/xml'})

response = requests.get('https://eovoc.spacebel.be/collections/datasets/items/SP4_OPER_HRI__I__2A_20030714T104451_20030714T104500_000213_0042_0246?httpAccept=application/vnd.iso.19139%2Bxml', verify=True,
   headers={'Accept': 'application/xml'})

payload = response.text

# 'cty' tells receiver what content-type to expect after decryption (i.e. the type of the secured content).  "application/" is left out of the media type.
# 'kid' key hint references the public key to which the JWE was encrypted; this can be used to determine the private key needed to decrypt the JWE.
# See https://www.rfc-editor.org/rfc/rfc7516.txt
#
protected_header = {'alg': 'RSA-OAEP',
 'cty': 'xml',
 'enc': 'A128GCM',
 'kid': se_key_kid }

# Encrypt the payload with the dek (public key of the server)
jwe_token = jwe.JWE(plaintext = payload.encode('utf-8'), recipient = se_key, protected = protected_header )

enc = jwe_token.serialize(compact=True)

Figure A.81

# Insert the metadata record (JOSE) in the catalog with 'POST'.
response = requests.post(endpoint_items, data = enc,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Content-Type': 'application/jose', 'Authorization':  'Bearer ' + access_token})

response

Figure A.82

<Response [201]>

Figure A.83

response.headers['Location']

Figure A.84

'https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/SP4_OPER_HRI__I__2A_20030714T104451_20030714T104500_000213_0042_0246'

Figure A.85

Retrieve the metadata record that was inserted from the OGC API-Records catalog.

# extract location of new image from HTTP header
url_location = endpoint_api_records + response.headers['Location']

# get it unencrypted.
response = requests.get(url_location, verify=bool(verify_ssl), headers={'Accept': 'application/geo+json'})
data = json.loads(response.text)
show_on_map(data)

Figure A.86

Make this Notebook Trusted to load map: File → Trust Notebook

A.8.  D113 GET /items/{item-id} with DCS (JWS)

Example: 3.5
> Access the OGC API-Records D113 /items/{item-id} to get a signed response (JWS format). The signature is used to verify the integrity of the response. The media type and value of the ``f'’ parameter are subject to change but allow to demonstrate the response format. The response is returned in clear (part 2 of the JWS token).

response = requests.get(endpoint_item + '?f=jws',
    verify=bool(verify_ssl),
    headers={'Accept': 'application/jose;profile=jws'})

response

Figure A.87

<Response [200]>

Figure A.88

The JWS response consists of three parts separated by a ``.'’ as explained in https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3

encdata = response.text
parts = encdata.split('.')

Figure A.89

# JWS token part 1 contains information about the key to use for verifying the signature.
from jwcrypto.common import base64url_decode
header = base64url_decode(parts[0])
header

Figure A.90

b'{"alg":"RS256","cty":"geo+json","iss":"https://ogc.demo.secure-dimensions.de","jku":"https://ogc.demo.secure-dimensions.de/.well-known/jwks.json","jwk":{"alg":"RS256","e":"AQAB","kid":"catalog-sign-key","kty":"RSA","n":"loOcM6QC6jUB6wnMM7S5px2OPkLbuycsA6qqJoFWPkXyFFx5Z6CJNOc-7li4WBprIAX65Sh6aOq3bBZ8FP3v7R7mZOo7e5fckvMTPOAzizkjXQuN8ZZoQta6xu9ryZoTkD2bOK11buLcc_ZtZt3pRBkgA_ZHZ7LJawhnkMGq_hpSMmDxkDoUHsJ5PLH1yATPhquQwdUWajUZJMs4S7Ns0LgCDoj0zeixq5K6lip4Mh6hSoRep8aB4UwshdV2VUbpBP-Tq6MF_DzjeOEgIlEnILu2E6JN83Dz_sjDEdrC5qNjEDLMnLJTzsrnOcdD3FrXiDTolXjmEjnq-mAfjL3IvQ"},"kid":"catalog-sign-key","typ":"JWT"}'

Figure A.91

# The "jwk" property contains the public key to verify the signature
from jwcrypto import jwk
data = json.loads(header)
data

Figure A.92

{'alg': 'RS256',
 'cty': 'geo+json',
 'iss': 'https://ogc.demo.secure-dimensions.de',
 'jku': 'https://ogc.demo.secure-dimensions.de/.well-known/jwks.json',
 'jwk': {'alg': 'RS256',
  'e': 'AQAB',
  'kid': 'catalog-sign-key',
  'kty': 'RSA',
  'n': 'loOcM6QC6jUB6wnMM7S5px2OPkLbuycsA6qqJoFWPkXyFFx5Z6CJNOc-7li4WBprIAX65Sh6aOq3bBZ8FP3v7R7mZOo7e5fckvMTPOAzizkjXQuN8ZZoQta6xu9ryZoTkD2bOK11buLcc_ZtZt3pRBkgA_ZHZ7LJawhnkMGq_hpSMmDxkDoUHsJ5PLH1yATPhquQwdUWajUZJMs4S7Ns0LgCDoj0zeixq5K6lip4Mh6hSoRep8aB4UwshdV2VUbpBP-Tq6MF_DzjeOEgIlEnILu2E6JN83Dz_sjDEdrC5qNjEDLMnLJTzsrnOcdD3FrXiDTolXjmEjnq-mAfjL3IvQ'},
 'kid': 'catalog-sign-key',
 'typ': 'JWT'}

Figure A.93

# extract the embedded public key needed to verify the signature

key = jwk.JWK.from_json(json.dumps(data['jwk']))
key

Figure A.94

{"kid":"catalog-sign-key","thumbprint":"uwatboW3aEXg3z0g1Ci6jyQzze5ZbpvYC_ahbTnwXs8"}

Figure A.95

# JWS token part 2 (the actual response)
from jwcrypto.common import base64url_decode
payload = base64url_decode(parts[1])
payload

Figure A.96

b'{"id": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001", "type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[2.83, 51.18], [2.83, 51.28], [3.02, 51.28], [3.02, 51.18], [2.83, 51.18]]]}, "properties": {"externalId": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001", "datetime": "2022-06-30T14:16:24", "start_datetime": "2022-03-07T14:02:00Z", "end_datetime": "2022-03-07T14:06:00Z", "recordUpdated": "2022-07-21T22:40:13Z", "type": "dataset", "created": "2019-05-22", "updated": "2022-06-30T14:16:24", "title": "Proba CHRIS Level 1A", "description": "CHRIS acquires a set of up to five images of each target during\\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\\n                    classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full\\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022\\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\\n                    distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\\n                    bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half\\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\\n                    Proba-1 passes are systematically acquired according to the current acquisition\\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\\n                    users. Observation over a new specific area can be performed by submitting the\\n                    request to add a new site to the acquisition plan.", "associations": [{"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP", "name": "Download", "description": null, "type": "WWW:DOWNLOAD", "rel": "WWW:DOWNLOAD"}, {"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG", "name": "QUICKLOOK", "description": null, "type": null, "rel": null}, {"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg", "name": "THUMBNAIL", "description": null, "type": null, "rel": null}], "extent": {"spatial": {"bbox": [[2.83, 51.18, 3.02, 51.28]], "crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"}}}, "links": [{"rel": "alternate", "type": "application/dcs+geo", "title": "This document as DCS + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=dcs+geo", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/jose", "title": "This document as JOSE + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jose", "hreflang": "en-US"}, {"rel": "self", "type": "application/jose;profile=jws", "title": "This document as JWS", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jws", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/geo+json", "title": "This document as GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=json", "hreflang": "en-US"}, {"rel": "alternate", "type": "text/html", "title": "This document as HTML", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=html", "hreflang": "en-US"}, {"rel": "collection", "type": "application/json", "title": "Collection URL", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main", "hreflang": "en-US"}], "assets": {}}'

Figure A.97

# JWS token part 3
from jwcrypto.common import base64url_decode
signature = base64url_decode(parts[2])
signature

Figure A.98

b"Lhd\x03;\xad\x8f\xe5#\xbd\x90\x15\x96\x9c\xdav\xfe,\xffk\xdeID\x937r\xa6\xcfo\x83\xe4\x83\xdb\xda\x19\x11\x17a+\xdb.\xbe\x0fa%7\x9b\xce~\x1e,\x83t\xd0_\xad\x953;K\r\x93\xfd\xb6\xb5\xbdnd\xc4#6\xd8O\x0f\xc5\xca\xb0e;1\x1d\xc0\x11f\x05\xe6% yQ\x19W\xa8KN\xf6\x07\xd5sS\xac\xbf\x87l\xc8\x01\x0f\xc7ZZ~+\xca\xffp\xc5\\\x16\xde\xcc\x9c\x7f\xafQ\x9d0\xee\xa9:\x00\xa4F\x95lV\xfd\x06\xf7\x1f4\x90j?\x1d;\x82\x8a~\xa1\xf1\x02\xf1a4\x1a'\xc28K\x13`v\xd6I\xb23\x91LK9,\x98K\xc6\xf3\xd9x+\xae^\x9c\xa8\x12t\xf0W'|\xdf\xb5%\x89\xed\xdb\x13t\x0f\xb4m\x11*\xfd\x07\xfc\x82\xbc\xea\x96\xd2\x0eO,]\\,\xf7\xb6\x97\xe2\xcela\xb4\x08\xa2\x19qV\xfd\xed\xff'\xc6\x9d\x0e\x17\xb2%D\xceh\xed\xf4l\n\x8fL9x\xf5\x90\xf3w\xbd\x83\xae"

Figure A.99

Verify the signature and thus the integrity of the response with the key extracted from part 1 of the header. If an exception is raised, then the signature does not match.

from jwcrypto import jws

jwstoken = jws.JWS()
jwstoken.deserialize(raw_jws = response.text)
# Verify the signature with the key from the header
jwstoken.verify(key)
payload = jwstoken.payload

payload

Figure A.100

b'{"id": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001", "type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[2.83, 51.18], [2.83, 51.28], [3.02, 51.28], [3.02, 51.18], [2.83, 51.18]]]}, "properties": {"externalId": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001", "datetime": "2022-06-30T14:16:24", "start_datetime": "2022-03-07T14:02:00Z", "end_datetime": "2022-03-07T14:06:00Z", "recordUpdated": "2022-07-21T22:40:13Z", "type": "dataset", "created": "2019-05-22", "updated": "2022-06-30T14:16:24", "title": "Proba CHRIS Level 1A", "description": "CHRIS acquires a set of up to five images of each target during\\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\\n                    classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full\\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022\\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\\n                    distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\\n                    bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half\\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\\n                    Proba-1 passes are systematically acquired according to the current acquisition\\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\\n                    users. Observation over a new specific area can be performed by submitting the\\n                    request to add a new site to the acquisition plan.", "associations": [{"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP", "name": "Download", "description": null, "type": "WWW:DOWNLOAD", "rel": "WWW:DOWNLOAD"}, {"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG", "name": "QUICKLOOK", "description": null, "type": null, "rel": null}, {"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg", "name": "THUMBNAIL", "description": null, "type": null, "rel": null}], "extent": {"spatial": {"bbox": [[2.83, 51.18, 3.02, 51.28]], "crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"}}}, "links": [{"rel": "alternate", "type": "application/dcs+geo", "title": "This document as DCS + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=dcs+geo", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/jose", "title": "This document as JOSE + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jose", "hreflang": "en-US"}, {"rel": "self", "type": "application/jose;profile=jws", "title": "This document as JWS", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jws", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/geo+json", "title": "This document as GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=json", "hreflang": "en-US"}, {"rel": "alternate", "type": "text/html", "title": "This document as HTML", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=html", "hreflang": "en-US"}, {"rel": "collection", "type": "application/json", "title": "Collection URL", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main", "hreflang": "en-US"}], "assets": {}}'

Figure A.101

Example: 3.6
> The signature is used to verify the integrity of the response, however, the key is retrieved from the originator of the response instead of using the included public key.

# Get the keyset published by the catalogue server from its well-known location.

response = requests.get('https://ogc.demo.secure-dimensions.de/.well-known/jwks.json', verify=True,
    headers={'Accept': 'application/json'})

response.text

Figure A.102

'{"keys":[{"kid":"catalog-sign-key","kty":"RSA","n":"loOcM6QC6jUB6wnMM7S5px2OPkLbuycsA6qqJoFWPkXyFFx5Z6CJNOc-7li4WBprIAX65Sh6aOq3bBZ8FP3v7R7mZOo7e5fckvMTPOAzizkjXQuN8ZZoQta6xu9ryZoTkD2bOK11buLcc_ZtZt3pRBkgA_ZHZ7LJawhnkMGq_hpSMmDxkDoUHsJ5PLH1yATPhquQwdUWajUZJMs4S7Ns0LgCDoj0zeixq5K6lip4Mh6hSoRep8aB4UwshdV2VUbpBP-Tq6MF_DzjeOEgIlEnILu2E6JN83Dz_sjDEdrC5qNjEDLMnLJTzsrnOcdD3FrXiDTolXjmEjnq-mAfjL3IvQ","e":"AQAB","use":"sig"},{"kid":"catalog-wrap-key","kty":"RSA","n":"utfDC-oXhPJVBn2KY-Lus_H6zn_lx5K6UNHySSXaAeu1cI1Q5UM782pvWI1iSxrq0s6a1a2faGocfR5XP7hugmQaQaTRHVTRL7L1cvu4oCLDm5DzI0CN_um6BH2zUW_MUBqpJuumgHEH17sMumg4jeH7x3oeW0xM7g-NzaCiQF5IEDMVHC9HGytpJcmCAev0vHR80oe7hSncJwbaa_Gryh3tH6YPcml-seGCJHPrLBIMVeTaSr-65gV050VZs2vF4W0bq_1AdObq1L1FISkHsayay0kleC4hq09uY5WqDkAHIIAxsj2R-weAE3M2UunIyKLFdXghnktlb9UKJavi_Q","e":"AQAB","use":"enc","key_ops":"wrapKey"},{"kid":"893ef3c8-c249-47a2-91e2-001a0b201647","kty":"RSA","n":"nhM1yyeJzcopJo79Cy_0jYbdhOL7XNzuYb2zi3HyTeQaNKwAzvt1c1MNMlm3Mt39kcB_mw5ehBZS1UZXGDWGV2BH5WZhyvTufxONizUlb65M5NHRMIKbmeDEYgyegKke6aaNaOl4QfSI6sd7JH6Zq_RtFBb85evfm74poRuV_JnS7u8j-kKrXUTgHNhwxHa8xuyz19o8506uWdDrYta53NYiuWdZ_So2Mzi3eK26o8rO3IX9Wk6nIWTYKmYetwYps0KOi7Q8hiH1RknrLvnNFT-z7eK2SZ3jycZCbDmD15KAasm5HQAlP3tOWJvq9_w3HiZakHZlNDwGbgCT1l_1pQ","e":"AQAB"}]}'

Figure A.103

import jwt
from jwcrypto import jwk, jwe

# Get the keyset from the catalog server (receiver)
server_keyset = jwk.JWKSet.from_json(response.text)
server_keyset

Figure A.104

{"keys":["{\"kid\":\"catalog-wrap-key\",\"thumbprint\":\"cqHuddqPaJd1vpyf7HBee_qR98eabtEIvpuFgnQlO4s\"}","{\"kid\":\"catalog-sign-key\",\"thumbprint\":\"uwatboW3aEXg3z0g1Ci6jyQzze5ZbpvYC_ahbTnwXs8\"}","{\"kid\":\"893ef3c8-c249-47a2-91e2-001a0b201647\",\"thumbprint\":\"ygIxjy7LMfiUVhDwEX_esDpGK8dsw3SnJgkF8yT4B6M\"}"]}

Figure A.105

# JWS header contains the "kid" of the key to be used for signature check.
data['kid']

Figure A.106

'catalog-sign-key'

Figure A.107

# JWS header contains also the well-known URL we just used to retrieve the server's keys.
data['jku']

Figure A.108

'https://ogc.demo.secure-dimensions.de/.well-known/jwks.json'

Figure A.109

se_key_kid = data['kid']
# Get the keypair for encryption by the catalog from the keyset via its 'kid' as there may be multiple.
key = server_keyset.get_key(kid=se_key_kid)
# Display the public key.
key.export(private_key=False, as_dict=True)

Figure A.110

{'kty': 'RSA',
 'use': 'sig',
 'kid': 'catalog-sign-key',
 'n': 'loOcM6QC6jUB6wnMM7S5px2OPkLbuycsA6qqJoFWPkXyFFx5Z6CJNOc-7li4WBprIAX65Sh6aOq3bBZ8FP3v7R7mZOo7e5fckvMTPOAzizkjXQuN8ZZoQta6xu9ryZoTkD2bOK11buLcc_ZtZt3pRBkgA_ZHZ7LJawhnkMGq_hpSMmDxkDoUHsJ5PLH1yATPhquQwdUWajUZJMs4S7Ns0LgCDoj0zeixq5K6lip4Mh6hSoRep8aB4UwshdV2VUbpBP-Tq6MF_DzjeOEgIlEnILu2E6JN83Dz_sjDEdrC5qNjEDLMnLJTzsrnOcdD3FrXiDTolXjmEjnq-mAfjL3IvQ',
 'e': 'AQAB'}

Figure A.111

from jwcrypto import jws

# decrypt the same JWS with the key directly retrieved from the server.

jwstoken = jws.JWS()
jwstoken.deserialize(raw_jws = encdata)
# Verify the signature with the key obtained from the well§known URL at the server.
jwstoken.verify(key)
payload = jwstoken.payload

payload

Figure A.112

b'{"id": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001", "type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[2.83, 51.18], [2.83, 51.28], [3.02, 51.28], [3.02, 51.18], [2.83, 51.18]]]}, "properties": {"externalId": "PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001", "datetime": "2022-06-30T14:16:24", "start_datetime": "2022-03-07T14:02:00Z", "end_datetime": "2022-03-07T14:06:00Z", "recordUpdated": "2022-07-21T22:40:13Z", "type": "dataset", "created": "2019-05-22", "updated": "2022-06-30T14:16:24", "title": "Proba CHRIS Level 1A", "description": "CHRIS acquires a set of up to five images of each target during\\n                    each acquisition sequence, these images are acquired when Proba-1 is pointing at\\n                    distinct angles with respect to the target. CHRIS Level 1A products (supplied in\\n                    HDF data files, version 4.1r3) include five formal CHRIS imaging modes,\\n                    classified as modes 1 to 5: \\u2022 MODE 1: Full swath width, 62 spectral bands, 773nm\\n                    / 1036nm, nadir ground sampling distance 34m @ 556km \\u2022 MODE 2 WATER BANDS: Full\\n                    swath width, 18 spectral bands, nadir ground sampling distance 17m @ 556km \\u2022\\n                    MODE 3 LAND CHANNELS: Full swath width, 18 spectral bands, nadir ground sampling\\n                    distance 17m @ 556km \\u2022 MODE 4 CHLOROPHYL BAND SET: Full swath width, 18 spectral\\n                    bands, nadir ground sampling distance 17m @ 556km \\u2022 MODE 5 LAND CHANNELS: Half\\n                    swath width, 37 spectral bands, nadir ground sampling distance 17m @ 556km All\\n                    Proba-1 passes are systematically acquired according to the current acquisition\\n                    plan, CHRIS data are processed every day to Level 1A and made available to ESA\\n                    users. Observation over a new specific area can be performed by submitting the\\n                    request to add a new site to the acquisition plan.", "associations": [{"href": "https://tpm-ds.eo.esa.int/oads/data/PROBA1-CHRIS/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP", "name": "Download", "description": null, "type": "WWW:DOWNLOAD", "rel": "WWW:DOWNLOAD"}, {"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/browse/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_BID.PNG", "name": "QUICKLOOK", "description": null, "type": null, "rel": null}, {"href": "http://tpm-ds.eo.esa.int/oads/meta/PROBA1-CHRIS/thumbnail/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001.SIP.ZIP_TIMG.jpg", "name": "THUMBNAIL", "description": null, "type": null, "rel": null}], "extent": {"spatial": {"bbox": [[2.83, 51.18, 3.02, 51.28]], "crs": "http://www.opengis.net/def/crs/OGC/1.3/CRS84"}}}, "links": [{"rel": "alternate", "type": "application/dcs+geo", "title": "This document as DCS + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=dcs+geo", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/jose", "title": "This document as JOSE + GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jose", "hreflang": "en-US"}, {"rel": "self", "type": "application/jose;profile=jws", "title": "This document as JWS", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=jws", "hreflang": "en-US"}, {"rel": "alternate", "type": "application/geo+json", "title": "This document as GeoJSON", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=json", "hreflang": "en-US"}, {"rel": "alternate", "type": "text/html", "title": "This document as HTML", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items/PR1_OPER_CHR_MO1_1P_20220307T140200_N51-240_E002-920_0001?f=html", "hreflang": "en-US"}, {"rel": "collection", "type": "application/json", "title": "Collection URL", "href": "https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main", "hreflang": "en-US"}], "assets": {}}'

Figure A.113

A.9.  Other signatures with DCS (JWS/CT)

Example: 3.7
> JWS/CT (Clear Text) signature creation: The signature is included in the original JSON metadata record (payload). See https://www.ietf.org/archive/id/draft-jordan-jws-ct-08.txt.

# Get a JSON metadata record (OGC 17-003r2) to be used for demonstrating the encoding.

response = requests.get('https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?mode=owc', verify=True,
    headers={'Accept': 'application/geo+json'})

datastr = response.text
data = json.loads(datastr)

Figure A.114

# create a key for signing (private+public).
srv_kid = "srvkid"
ss_key = jwk.JWK(generate='RSA', kid=srv_kid, use="sig")

ss_key

Figure A.115

{"kid":"srvkid","thumbprint":"PKZ9rKjdrxgH-RsxRzz0KgSvz1GvXf0j8sEbLSQdVI0"}

Figure A.116

import jwt
import jcs
from jwcrypto import jwk, jwe, jws

protected_header = {
 'alg': 'RS256',
 "kty": "RSA",
 'cty': 'geo+json',
 'kid': srv_kid }

# normalise the JSON to compute the JWS.
payload = str(jcs.canonicalize( data ))

jwstoken = jws.JWS(payload.encode('utf-8'))
jwstoken.add_signature(key = ss_key,
    alg = None,
    protected = protected_header)

Figure A.117

enc = jwstoken.serialize(compact = True)

Figure A.118

# Remove middle part of the token to create a JWS token without payload.
parts = enc.split('.')
jwsstr = parts[0] + ".." + parts[2]
jwsstr

Figure A.119

'eyJhbGciOiJSUzI1NiIsImN0eSI6Imdlbytqc29uIiwia2lkIjoic3J2a2lkIiwia3R5IjoiUlNBIn0..Jw0cFyewMQApaJZYpMjzqGxiDfKh19ICzWtw8tpfRE1lUv9yn4_51X2C8EZkic_9QQ16BNa9k4HYtj0r7RigFmdra6aYps9nHuv1ATm3g6e6hVTYP3bgHKfzvyA2NkngU1eu9NafDjq4BlPI73-G6U_YRIFeEVnYcFiBfgOSaRICIpTczqgBqgWEaZnEUXq5v4dGT6aZa8JNoMMaNvOcP8dsGk2-JLI3xkBhtcgHo7N1kQtC0x7hJ13b26BhS-F_6qlrNb3k62wRQx7fJj0YMpqrJuUUE0GFGKq2fCC76N_efn3XtLIuXPDTCOViFZf6LgUfRQV5-qATv7rygIGyJg'

Figure A.120

Create the JWS/CT

# add signature property to the original JSON object (data) and print result.
data['signature'] = jwsstr

jstr = json.dumps(data, indent=3)
md("```json\n" + jstr + "\n```\n")

Figure A.121

{
  
"bbox": [
     
5.8,
     
54.78,
     
7.85,
     
55.89
  
],
  
"geometry": {
     
"coordinates": [
        
[
           
[
              
6.17,
              
55.89
           
],
           
[
              
5.8,
              
55.01
           
],
           
[
              
7.45,
              
54.78
           
],
           
[
              
7.85,
              
55.66
           
]
        
]
     
],
     
"type": "Polygon"
  
},
  
"id": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?mode=owc",
  
"type": "Feature",
  
"properties": {
     
"date": "2002-11-15T10:04:04.824Z/2002-11-15T10:04:19.914Z",
     
"identifier": "ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000",
     
"kind": "http://purl.org/dc/dcmitype/Dataset",
     
"parentIdentifier": "ENVISAT.ASA.APS_1P",
     
"productInformation": {
        
"referenceSystemIdentifier": "epsg:4326",
        
"productType": "ASA_APS_1P",
        
"availabilityTime": "2002-11-15T10:04:19.914Z"
     
},
     
"links": {
        
"data": [
           
{
              
"href": "https://esar-ds.eo.esa.int/oads/data/ASA_APS_1P/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000.N1",
              
"type": "application/x-binary",
              
"title": "Download"
           
}
        
],
        
"previews": [
           
{
              
"href": "http://esar-ds.eo.esa.int/oads/meta/ASA_APS_1P/browse/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000.N1_BID.JPG",
              
"type": "image/jpeg",
              
"title": "QUICKLOOK"
           
},
           
{
              
"href": "http://esar-ds.eo.esa.int/oads/meta/ASA_APS_1P/thumbnail/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000.N1_TIMG.jpg",
              
"type": "image/jpeg",
              
"title": "THUMBNAIL"
           
}
        
],
        
"up": [
           
{
              
"href": "https://eovoc.spacebel.be/collections/series/items/ENVISAT.ASA.APS_1P?mode=owc",
              
"title": "OGC 17-084r1 metadata",
              
"type": "application/geo+json"
           
}
        
],
        
"alternates": [
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/atom%2Bxml",
              
"type": "application/atom+xml",
              
"title": "Atom format"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/gml%2Bxml&recordSchema=om",
              
"type": "application/gml+xml;profile=\"http://www.opengis.net/spec/EOMPOM/1.1\"",
              
"title": "OGC 10-157r4 metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/gml%2Bxml&recordSchema=om10",
              
"type": "application/gml+xml;profile=\"http://www.opengis.net/spec/EOMPOM/1.0\"",
              
"title": "OGC 10-157r3 metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000",
              
"type": "application/geo+json;profile=\"http://www.opengis.net/spec/ogcapi-features-1/1.0\"",
              
"title": "OGC 17-069r3 metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/geo%2Bjson;profile=https://stacspec.org",
              
"type": "application/geo+json;profile=\"https://stacspec.org\"",
              
"title": "STAC metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/vnd.iso.19139%2Bxml",
              
"type": "application/vnd.iso.19139+xml",
              
"title": "ISO 19139 metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/ld%2Bjson",
              
"type": "application/ld+json",
              
"title": "JSON-LD metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/ld%2Bjson;profile=https://schema.org",
              
"type": "application/ld+json;profile=\"https://schema.org\"",
              
"title": "JSON-LD (schema.org) metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/ld%2Bjson;profile=http://data.europa.eu/930/",
              
"type": "application/ld+json;profile=\"http://data.europa.eu/930/\"",
              
"title": "JSON-LD (GeoDCAT-AP) metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/rdf%2Bxml",
              
"type": "application/rdf+xml",
              
"title": "RDF/XML metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/rdf%2Bxml;profile=https://schema.org",
              
"type": "application/rdf+xml;profile=\"https://schema.org\"",
              
"title": "RDF/XML (schema.org) metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=application/rdf%2Bxml;profile=http://data.europa.eu/930/",
              
"type": "application/rdf+xml;profile=\"http://data.europa.eu/930/\"",
              
"title": "RDF/XML (GeoDCAT-AP) metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=text/turtle",
              
"type": "text/turtle",
              
"title": "Turtle metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=text/turtle;profile=https://schema.org",
              
"type": "text/turtle;profile=\"https://schema.org\"",
              
"title": "Turtle (schema.org) metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=text/turtle;profile=http://data.europa.eu/930/",
              
"type": "text/turtle;profile=\"http://data.europa.eu/930/\"",
              
"title": "Turtle (GeoDCAT-AP) metadata"
           
},
           
{
              
"href": "https://eovoc.spacebel.be/collections/datasets/items/ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000?httpAccept=text/html",
              
"type": "text/html",
              
"title": "HTML"
           
}
        
]
     
},
     
"title": "ASA_APS_1PNESA20021115_100404_000000152011_00151_03712_0000",
     
"updated": "2022-07-08T16:51:53Z",
     
"acquisitionInformation": [
        
{
           
"acquisitionParameters": {
              
"polarisationMode": "D",
              
"acquisitionType": "NOMINAL",
              
"polarisationChannels": "VV, VH",
              
"swathIdentifier": "IS2",
              
"resolution": 30,
              
"endingDateTime": "2002-11-15T10:04:19.914Z",
              
"orbitNumber": 3712,
              
"operationalMode": "AP",
              
"beginningDateTime": "2002-11-15T10:04:04.824Z",
              
"wrsLongitudeGrid": "151",
              
"wrsLatitudeGrid": "2490",
              
"startTimeFromAscendingNode": 2079834,
              
"completionTimeFromAscendingNode": 2094924,
              
"orbitDirection": "DESCENDING"
           
},
           
"instrument": {
              
"instrumentShortName": "ASAR",
              
"sensorType": "RADAR"
           
},
           
"platform": {
              
"platformShortName": "Envisat"
           
}
        
}
     
],
     
"status": "ARCHIVED"
  
},
  
"signature": "eyJhbGciOiJSUzI1NiIsImN0eSI6Imdlbytqc29uIiwia2lkIjoic3J2a2lkIiwia3R5IjoiUlNBIn0..Jw0cFyewMQApaJZYpMjzqGxiDfKh19ICzWtw8tpfRE1lUv9yn4_51X2C8EZkic_9QQ16BNa9k4HYtj0r7RigFmdra6aYps9nHuv1ATm3g6e6hVTYP3bgHKfzvyA2NkngU1eu9NafDjq4BlPI73-G6U_YRIFeEVnYcFiBfgOSaRICIpTczqgBqgWEaZnEUXq5v4dGT6aZa8JNoMMaNvOcP8dsGk2-JLI3xkBhtcgHo7N1kQtC0x7hJ13b26BhS-F_6qlrNb3k62wRQx7fJj0YMpqrJuUUE0GFGKq2fCC76N_efn3XtLIuXPDTCOViFZf6LgUfRQV5-qATv7rygIGyJg"
}

Figure A.122

Example: 3.8
> JWS/CT (Clear Text) signature validation: The signature is included in the original JSON metadata record (payload). See https://www.ietf.org/archive/id/draft-jordan-jws-ct-08.txt.

# jstr is signed JSON metadata
data = json.loads(jstr)

# Fetch the Signature Property String containing the JWS token without a payload part.
sig = data['signature']
sig

Figure A.123

'eyJhbGciOiJSUzI1NiIsImN0eSI6Imdlbytqc29uIiwia2lkIjoic3J2a2lkIiwia3R5IjoiUlNBIn0..Jw0cFyewMQApaJZYpMjzqGxiDfKh19ICzWtw8tpfRE1lUv9yn4_51X2C8EZkic_9QQ16BNa9k4HYtj0r7RigFmdra6aYps9nHuv1ATm3g6e6hVTYP3bgHKfzvyA2NkngU1eu9NafDjq4BlPI73-G6U_YRIFeEVnYcFiBfgOSaRICIpTczqgBqgWEaZnEUXq5v4dGT6aZa8JNoMMaNvOcP8dsGk2-JLI3xkBhtcgHo7N1kQtC0x7hJ13b26BhS-F_6qlrNb3k62wRQx7fJj0YMpqrJuUUE0GFGKq2fCC76N_efn3XtLIuXPDTCOViFZf6LgUfRQV5-qATv7rygIGyJg'

Figure A.124

# Remove the Signature Property String
del data['signature']
# Canonicalize the Remaining JSON Object
payload = str(jcs.canonicalize( data ))

# Validate the JWS String (Annex F of JWS RFC7515)
jwstoken = jws.JWS(payload = None)
jwstoken.deserialize(raw_jws = sig)

try:
    jwstoken.verify(key = ss_key.public(), detached_payload = payload)
    print("JWS signature verification completed.")
except jws.InvalidJWSSignature:
    print("JWS signature verification failed.")

Figure A.125

JWS signature verification completed.

Figure A.126

A.10.  D112 (CSW) GetCapabilities without DCS

See information available at https://cat.csiss.gmu.edu/CSW_Client-Guide.pdf.

Example: 4.1
> Access the GMU CSW D112 (GetCapabilities) to retrieve supported queryables.

csw_endpoint_items = endpoint_csw + "?SERVICE=CSW&REQUEST=GetCapabilities&VERSION=2.0.2&sections=OperationsMetadata"

response = requests.get(csw_endpoint_items,
    verify=True,
    headers={})

# Extract information about GetRecords from the response.
rt = ElementTree.fromstring(response.text)
r = rt.find("{http://www.opengis.net/ows}OperationsMetadata/{http://www.opengis.net/ows}Operation[@name='GetRecords']")

try:
    xmltxt = ElementTree.tostring(r, encoding='unicode', method='xml')
except:
    xmltxt= 'Not found.'

md("```xml\n" + xmltxt + "\n```\n")

Figure A.127

<ns0:Operation xmlns:ns0="http://www.opengis.net/ows" xmlns:ns1="http://www.w3.org/1999/xlink" name="GetRecords"><ns0:DCP><ns0:HTTP><ns0:Get ns1:type="simple" ns1:href="https://cat.csiss.gmu.edu/ows18" /><ns0:Post ns1:type="simple" ns1:href="https://cat.csiss.gmu.edu/ows18" /></ns0:HTTP></ns0:DCP><ns0:Parameter name="CONSTRAINTLANGUAGE"><ns0:Value>CQL_TEXT</ns0:Value><ns0:Value>FILTER</ns0:Value></ns0:Parameter><ns0:Parameter name="ElementSetName"><ns0:Value>brief</ns0:Value><ns0:Value>full</ns0:Value><ns0:Value>summary</ns0:Value></ns0:Parameter><ns0:Parameter name="outputFormat"><ns0:Value>application/json</ns0:Value><ns0:Value>application/xml</ns0:Value></ns0:Parameter><ns0:Parameter name="outputSchema"><ns0:Value>http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/</ns0:Value><ns0:Value>http://www.interlis.ch/INTERLIS2.3</ns0:Value><ns0:Value>http://www.isotc211.org/2005/gmd</ns0:Value><ns0:Value>http://www.opengis.net/cat/csw/2.0.2</ns0:Value><ns0:Value>http://www.opengis.net/cat/csw/csdgm</ns0:Value><ns0:Value>http://www.w3.org/2005/Atom</ns0:Value><ns0:Value>urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0</ns0:Value></ns0:Parameter><ns0:Parameter name="resultType"><ns0:Value>hits</ns0:Value><ns0:Value>results</ns0:Value><ns0:Value>validate</ns0:Value></ns0:Parameter><ns0:Parameter name="typeNames"><ns0:Value>csw:Record</ns0:Value><ns0:Value>gmd:MD_Metadata</ns0:Value><ns0:Value>rim:RegistryObject</ns0:Value></ns0:Parameter><ns0:Constraint name="AdditionalQueryables"><ns0:Value>apiso:AccessConstraints</ns0:Value><ns0:Value>apiso:Bands</ns0:Value><ns0:Value>apiso:Classification</ns0:Value><ns0:Value>apiso:CloudCover</ns0:Value><ns0:Value>apiso:ConditionApplyingToAccessAndUse</ns0:Value><ns0:Value>apiso:Contributor</ns0:Value><ns0:Value>apiso:Creator</ns0:Value><ns0:Value>apiso:Degree</ns0:Value><ns0:Value>apiso:Instrument</ns0:Value><ns0:Value>apiso:Lineage</ns0:Value><ns0:Value>apiso:OtherConstraints</ns0:Value><ns0:Value>apiso:Platform</ns0:Value><ns0:Value>apiso:Publisher</ns0:Value><ns0:Value>apiso:Relation</ns0:Value><ns0:Value>apiso:ResponsiblePartyRole</ns0:Value><ns0:Value>apiso:SensorType</ns0:Value><ns0:Value>apiso:SpecificationDate</ns0:Value><ns0:Value>apiso:SpecificationDateType</ns0:Value><ns0:Value>apiso:SpecificationTitle</ns0:Value></ns0:Constraint><ns0:Constraint name="SupportedDublinCoreQueryables"><ns0:Value>csw:AnyText</ns0:Value><ns0:Value>dc:contributor</ns0:Value><ns0:Value>dc:creator</ns0:Value><ns0:Value>dc:date</ns0:Value><ns0:Value>dc:format</ns0:Value><ns0:Value>dc:identifier</ns0:Value><ns0:Value>dc:language</ns0:Value><ns0:Value>dc:publisher</ns0:Value><ns0:Value>dc:relation</ns0:Value><ns0:Value>dc:rights</ns0:Value><ns0:Value>dc:source</ns0:Value><ns0:Value>dc:subject</ns0:Value><ns0:Value>dc:title</ns0:Value><ns0:Value>dc:type</ns0:Value><ns0:Value>dct:abstract</ns0:Value><ns0:Value>dct:alternative</ns0:Value><ns0:Value>dct:modified</ns0:Value><ns0:Value>dct:spatial</ns0:Value><ns0:Value>ows:BoundingBox</ns0:Value></ns0:Constraint><ns0:Constraint name="SupportedISOQueryables"><ns0:Value>apiso:Abstract</ns0:Value><ns0:Value>apiso:AlternateTitle</ns0:Value><ns0:Value>apiso:AnyText</ns0:Value><ns0:Value>apiso:BoundingBox</ns0:Value><ns0:Value>apiso:CRS</ns0:Value><ns0:Value>apiso:CouplingType</ns0:Value><ns0:Value>apiso:CreationDate</ns0:Value><ns0:Value>apiso:Denominator</ns0:Value><ns0:Value>apiso:DistanceUOM</ns0:Value><ns0:Value>apiso:DistanceValue</ns0:Value><ns0:Value>apiso:Format</ns0:Value><ns0:Value>apiso:GeographicDescriptionCode</ns0:Value><ns0:Value>apiso:HasSecurityConstraints</ns0:Value><ns0:Value>apiso:Identifier</ns0:Value><ns0:Value>apiso:KeywordType</ns0:Value><ns0:Value>apiso:Language</ns0:Value><ns0:Value>apiso:Modified</ns0:Value><ns0:Value>apiso:OperatesOn</ns0:Value><ns0:Value>apiso:OperatesOnIdentifier</ns0:Value><ns0:Value>apiso:OperatesOnName</ns0:Value><ns0:Value>apiso:Operation</ns0:Value><ns0:Value>apiso:OrganisationName</ns0:Value><ns0:Value>apiso:ParentIdentifier</ns0:Value><ns0:Value>apiso:PublicationDate</ns0:Value><ns0:Value>apiso:ResourceLanguage</ns0:Value><ns0:Value>apiso:RevisionDate</ns0:Value><ns0:Value>apiso:ServiceType</ns0:Value><ns0:Value>apiso:ServiceTypeVersion</ns0:Value><ns0:Value>apiso:Subject</ns0:Value><ns0:Value>apiso:TempExtent_begin</ns0:Value><ns0:Value>apiso:TempExtent_end</ns0:Value><ns0:Value>apiso:Title</ns0:Value><ns0:Value>apiso:TopicCategory</ns0:Value><ns0:Value>apiso:Type</ns0:Value></ns0:Constraint></ns0:Operation>

Figure A.128

A.11.  D112 (CSW) GetRecords without DCS

Example: 4.2
> Access the GMU CSW D112 (GetRecords).

csw_endpoint_items = endpoint_csw + "?SERVICE=CSW&REQUEST=GetRecords&VERSION=2.0.2&ElementSetName=full&typeNames=gmd:MD_Metadata&resultType=results&outputSchema=http://www.isotc211.org/2005/gmd&maxRecords=1"

response = requests.get(csw_endpoint_items,
    verify=True,
    headers={})
# headers={'Accept': 'application/xml'})

xmlstr = minidom.parseString(response.text).toprettyxml(indent='  ',newl='')
md("```xml\n" + xmlstr + "\n```\n")

Figure A.129

<?xml version="1.0" ?><!-- pycsw 3.0.dev0 --><csw:GetRecordsResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dct="http://purl.org/dc/terms/" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gml="http://www.opengis.net/gml" xmlns:ows="http://www.opengis.net/ows" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gco="http://www.isotc211.org/2005/gco" version="2.0.2" xsi:schemaLocation="http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd">  <csw:SearchStatus timestamp="2022-10-21T15:19:25Z"/>  <csw:SearchResults numberOfRecordsMatched="8" numberOfRecordsReturned="1" nextRecord="2" recordSchema="http://www.isotc211.org/2005/gmd" elementSet="full">    <gmd:MD_Metadata xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd">      <gmd:fileIdentifier>        <gco:CharacterString>urn:uuid:b1e7ef9a-0146-11ed-b12e-d19c2be36fcc</gco:CharacterString>      </gmd:fileIdentifier>      <gmd:language>        <gco:CharacterString>en-US</gco:CharacterString>      </gmd:language>      <gmd:hierarchyLevel>        <gmd:MD_ScopeCode codeSpace="ISOTC211/19115" codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="vector digital data">vector digital data</gmd:MD_ScopeCode>      </gmd:hierarchyLevel>      <gmd:contact>        <gmd:CI_ResponsibleParty>          <gmd:organisationName>            <gco:CharacterString>Earth Data Analysis Center</gco:CharacterString>          </gmd:organisationName>        </gmd:CI_ResponsibleParty>      </gmd:contact>      <gmd:dateStamp>        <gco:Date/>      </gmd:dateStamp>      <gmd:metadataStandardName>        <gco:CharacterString>ISO19115</gco:CharacterString>      </gmd:metadataStandardName>      <gmd:metadataStandardVersion>        <gco:CharacterString>2003/Cor.1:2006</gco:CharacterString>      </gmd:metadataStandardVersion>      <gmd:identificationInfo>        <gmd:MD_DataIdentification id="urn:uuid:b1e7ef9a-0146-11ed-b12e-d19c2be36fcc">          <gmd:citation>            <gmd:CI_Citation>              <gmd:title>                <gco:CharacterString>Current Core Based Statistical Areas for San Miguel County, New Mexico, 2006se TIGER</gco:CharacterString>              </gmd:title>              <gmd:date>                <gmd:CI_Date>                  <gmd:date>                    <gco:Date>20080108</gco:Date>                  </gmd:date>                  <gmd:dateType>                    <gmd:CI_DateTypeCode codeSpace="ISOTC211/19115" codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>                  </gmd:dateType>                </gmd:CI_Date>              </gmd:date>            </gmd:CI_Citation>          </gmd:citation>          <gmd:abstract>            <gco:CharacterString>The 2006 Second Edition TIGER/Line files are an extract of selected geographic and cartographic information from the Census TIGER database.  The geographic coverage for a single TIGER/Line file is a county or statistical equivalent entity, with the coverage area based on the latest available governmental unit boundaries. The Census TIGER database represents a seamless national file with no overlaps or gaps between parts.  However, each county-based TIGER/Line file is designed to stand alone as an independent data set or the files can be combined to cover the whole Nation.  The 2006 Second Edition  TIGER/Line files consist of line segments representing physical features and governmental and statistical boundaries.

This shapefile represents the current Core Based Statistical Areas in the 2006 TIGER Second Edition dataset for San Miguel County, NM.</gco:CharacterString>          </gmd:abstract>          <gmd:descriptiveKeywords>            <gmd:MD_Keywords>              <gmd:keyword>                <gco:CharacterString>boundaries</gco:CharacterString>              </gmd:keyword>            </gmd:MD_Keywords>          </gmd:descriptiveKeywords>          <gmd:language>            <gco:CharacterString/>          </gmd:language>          <gmd:extent>            <gmd:EX_Extent>              <gmd:geographicElement>                <gmd:EX_GeographicBoundingBox>                  <gmd:westBoundLongitude>                    <gco:Decimal>-105.72</gco:Decimal>                  </gmd:westBoundLongitude>                  <gmd:eastBoundLongitude>                    <gco:Decimal>-103.64</gco:Decimal>                  </gmd:eastBoundLongitude>                  <gmd:southBoundLatitude>                    <gco:Decimal>35.04</gco:Decimal>                  </gmd:southBoundLatitude>                  <gmd:northBoundLatitude>                    <gco:Decimal>35.87</gco:Decimal>                  </gmd:northBoundLatitude>                </gmd:EX_GeographicBoundingBox>              </gmd:geographicElement>            </gmd:EX_Extent>          </gmd:extent>        </gmd:MD_DataIdentification>      </gmd:identificationInfo>      <gmd:distributionInfo>        <gmd:MD_Distribution>          <gmd:transferOptions>            <gmd:MD_DigitalTransferOptions>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>http://rgis.unm.edu</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/services/ogc/wms?SERVICE=wms&#x26;REQUEST=GetCapabilities&#x26;VERSION=1.1.1</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/services/ogc/wfs?SERVICE=wfs&#x26;REQUEST=GetCapabilities&#x26;VERSION=1.0.0</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.shp</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.original.zip</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.gml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.kml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.geojson</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.json</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.csv</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.xls</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/FGDC-STD-001-1998.xml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/FGDC-STD-001-1998.html</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19115:2003.xml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19115:2003.html</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19119:WMS.xml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19119:WFS.xml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19110.xml</gmd:URL>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString/>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>              <gmd:onLine>                <gmd:CI_OnlineResource>                  <gmd:linkage>                    <gmd:URL/>                  </gmd:linkage>                  <gmd:protocol>                    <gco:CharacterString/>                  </gmd:protocol>                  <gmd:name>                    <gco:CharacterString/>                  </gmd:name>                  <gmd:description>                    <gco:CharacterString>ZIP</gco:CharacterString>                  </gmd:description>                </gmd:CI_OnlineResource>              </gmd:onLine>            </gmd:MD_DigitalTransferOptions>          </gmd:transferOptions>        </gmd:MD_Distribution>      </gmd:distributionInfo>    </gmd:MD_Metadata>  </csw:SearchResults></csw:GetRecordsResponse>

Figure A.130

A.12.  D112 (CSW) GetRecordByID without DCS

Example: 4.3
> Access the GMU CSW D112 (GetRecordByID).

item_id = "urn:uuid:b1e7ef9a-0146-11ed-b12e-d19c2be36fcc"
csw_endpoint_item = endpoint_csw + "?SERVICE=CSW&REQUEST=GetRecordById&VERSION=2.0.2&id=" + item_id + "&ElementSetName=full&outputSchema=http://www.isotc211.org/2005/gmd&outputFormat=application/xml"

response = requests.get(csw_endpoint_item,
    verify=True,
    headers={})

# Extract ISO19139 metadata record from the response.
rt = ElementTree.fromstring(response.text)
r = rt.find('{*}MD_Metadata')

try:
    xmltxt = ElementTree.tostring(r, encoding='unicode', method='xml')
except:
    xmltxt= 'Not found.'

md("```xml\n" + xmltxt + "\n```\n")

Figure A.131

<ns0:MD_Metadata xmlns:ns0="http://www.isotc211.org/2005/gmd" xmlns:ns2="http://www.isotc211.org/2005/gco" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/csw/2.0.2/profiles/apiso/1.0.0/apiso.xsd"><ns0:fileIdentifier><ns2:CharacterString>urn:uuid:b1e7ef9a-0146-11ed-b12e-d19c2be36fcc</ns2:CharacterString></ns0:fileIdentifier><ns0:language><ns2:CharacterString>en-US</ns2:CharacterString></ns0:language><ns0:hierarchyLevel><ns0:MD_ScopeCode codeSpace="ISOTC211/19115" codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="vector digital data">vector digital data</ns0:MD_ScopeCode></ns0:hierarchyLevel><ns0:contact><ns0:CI_ResponsibleParty><ns0:organisationName><ns2:CharacterString>Earth Data Analysis Center</ns2:CharacterString></ns0:organisationName></ns0:CI_ResponsibleParty></ns0:contact><ns0:dateStamp><ns2:Date /></ns0:dateStamp><ns0:metadataStandardName><ns2:CharacterString>ISO19115</ns2:CharacterString></ns0:metadataStandardName><ns0:metadataStandardVersion><ns2:CharacterString>2003/Cor.1:2006</ns2:CharacterString></ns0:metadataStandardVersion><ns0:identificationInfo><ns0:MD_DataIdentification id="urn:uuid:b1e7ef9a-0146-11ed-b12e-d19c2be36fcc"><ns0:citation><ns0:CI_Citation><ns0:title><ns2:CharacterString>Current Core Based Statistical Areas for San Miguel County, New Mexico, 2006se TIGER</ns2:CharacterString></ns0:title><ns0:date><ns0:CI_Date><ns0:date><ns2:Date>20080108</ns2:Date></ns0:date><ns0:dateType><ns0:CI_DateTypeCode codeSpace="ISOTC211/19115" codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</ns0:CI_DateTypeCode></ns0:dateType></ns0:CI_Date></ns0:date></ns0:CI_Citation></ns0:citation><ns0:abstract><ns2:CharacterString>The 2006 Second Edition TIGER/Line files are an extract of selected geographic and cartographic information from the Census TIGER database.  The geographic coverage for a single TIGER/Line file is a county or statistical equivalent entity, with the coverage area based on the latest available governmental unit boundaries. The Census TIGER database represents a seamless national file with no overlaps or gaps between parts.  However, each county-based TIGER/Line file is designed to stand alone as an independent data set or the files can be combined to cover the whole Nation.  The 2006 Second Edition  TIGER/Line files consist of line segments representing physical features and governmental and statistical boundaries.

This shapefile represents the current Core Based Statistical Areas in the 2006 TIGER Second Edition dataset for San Miguel County, NM.</ns2:CharacterString></ns0:abstract><ns0:descriptiveKeywords><ns0:MD_Keywords><ns0:keyword><ns2:CharacterString>boundaries</ns2:CharacterString></ns0:keyword></ns0:MD_Keywords></ns0:descriptiveKeywords><ns0:language><ns2:CharacterString /></ns0:language><ns0:extent><ns0:EX_Extent><ns0:geographicElement><ns0:EX_GeographicBoundingBox><ns0:westBoundLongitude><ns2:Decimal>-105.72</ns2:Decimal></ns0:westBoundLongitude><ns0:eastBoundLongitude><ns2:Decimal>-103.64</ns2:Decimal></ns0:eastBoundLongitude><ns0:southBoundLatitude><ns2:Decimal>35.04</ns2:Decimal></ns0:southBoundLatitude><ns0:northBoundLatitude><ns2:Decimal>35.87</ns2:Decimal></ns0:northBoundLatitude></ns0:EX_GeographicBoundingBox></ns0:geographicElement></ns0:EX_Extent></ns0:extent></ns0:MD_DataIdentification></ns0:identificationInfo><ns0:distributionInfo><ns0:MD_Distribution><ns0:transferOptions><ns0:MD_DigitalTransferOptions><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>http://rgis.unm.edu</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/services/ogc/wms?SERVICE=wms&#x26;REQUEST=GetCapabilities&#x26;VERSION=1.1.1</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/services/ogc/wfs?SERVICE=wfs&#x26;REQUEST=GetCapabilities&#x26;VERSION=1.0.0</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.shp</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.original.zip</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.gml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.kml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.geojson</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.json</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.csv</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/tgr2006se_sanm_cbsacu.derived.xls</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/FGDC-STD-001-1998.xml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/FGDC-STD-001-1998.html</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19115:2003.xml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19115:2003.html</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19119:WMS.xml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19119:WFS.xml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL>https://gstore.unm.edu/apps/rgisarchive/datasets/5b718539-f99f-43a0-9a7e-2cefed2df238/metadata/ISO-19110.xml</ns0:URL></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString /></ns0:description></ns0:CI_OnlineResource></ns0:onLine><ns0:onLine><ns0:CI_OnlineResource><ns0:linkage><ns0:URL /></ns0:linkage><ns0:protocol><ns2:CharacterString /></ns0:protocol><ns0:name><ns2:CharacterString /></ns0:name><ns0:description><ns2:CharacterString>ZIP</ns2:CharacterString></ns0:description></ns0:CI_OnlineResource></ns0:onLine></ns0:MD_DigitalTransferOptions></ns0:transferOptions></ns0:MD_Distribution></ns0:distributionInfo></ns0:MD_Metadata>

Figure A.132

A.13.  Subscriptions to OGC API-Records

See information available at https://ogc.demo.secure-dimensions.de/sms/api.

Prepare key pairs See https://jwcrypto.readthedocs.io/en/latest/jwk.html

    srv_kid = "srvkid"
    cli_kid = "clikid"
    ss_key = jwk.JWK(generate='RSA', kid=srv_kid, use="sig")
    se_key = jwk.JWK(generate='RSA', kid=srv_kid, use="enc")

    cs_key = jwk.JWK(generate='RSA', kid=cli_kid, use="sig")
    ce_key = jwk.JWK(generate='RSA', kid=cli_kid, use="enc")

    # client key pair for encryption (public+private)
    ce_key.export()

Figure A.133

'{"d":"_rw1-M-daUJgW80IuhltH3uFpv0lttiSbeIa_A1Gn75mc48w3kaTXH0RHpC6whAz88N0fKxbJwDbmsUs6PJ1BvkZJTu04nOtlTF0GuWj7uhAY5S-zj-Gq5odBUyi72S8aSOpKMFOeiwcYZxWs-L4_attPMJSDgMxTzHtpTjmZvTSSESuD-KYkJPTbvvA7UVBIt43usuNTUhxDVcQY-emGTAYsicOeZGWFGWYo24LjX1RKP95IztCa0Mw2MPEPE8rA1muvfkk3MnhntdOLRTlw0TexpAwNGn0_2hy80uFwD6vRPOCzocLZT0FdllgOLYzr4JwXE_G1MIVIgTXnwZB","dp":"P60BtUnExG1zxR6obqGnP5z2yCGtp0LXjrg5tFJa6H6OPv_wALbPSfEf67Dj8IvQTmZnPDVmOT21GRbB2fV7LtqfHMpt0-bTMHlwBkR0BJo47BF0PHwnX_MtepHzvYA36roXkimS_8Oc_PR4DqPa0up3DbsO6Bid0xwBRkcYXCU","dq":"TQ466gqzsiLTQK3VTKg1J-zY4Gp-xocHHPALnrrj96aeHUWMb09zArFxKIMLpzDHs24DN0PxyVC2h6hjQAP-dheSYFRwcQOF5uj1NkfFvyTf19hTzP1pBKTTNm9exMSwAEXel4bJlfqFs89k6NGsFTEuhVnavf7eY7FjRfv-itU","e":"AQAB","kid":"clikid","kty":"RSA","n":"2qBsAlkltTmv-oMoLVsay9B-CAo_3ie5fi8Mg9Aph72w9uR5gEcfz6A-rsPLMH8buNwuUIoKo73NRc-glXBA9XUSvNn86dJiHTEyKAZm9ybm3_qZGSDl0KlgqDNx-qGOi2r5JSN3AQYlAvLi1_qSaIVDOwKQJY7NZR1C7Z2l7jqQfSxEoIRSt_K57Gt9wo7GIHcuOnzr30zTYg1UzSQx_b8bxdoUDWrNgCJYw9NuwmvRkjaBJr___bMbKz0LnqlwfI3eHqCYb8bfcR9YdL17f4vIAtkk_XWXjB-hldoPwQiVpBno4Bz14PXaDFB4p8d3BcrLwKz3ESy6sW6CiZmIQw","p":"-uTjBeriYAs1L11usnn1B763ki0flOK5Lcj_r2nFZ1-qwd52fZqSoIkSKJ06zPmIkYSuVDLzfzTP4mKj_NmWBakxmLAdR2jIsGQ8BU1IdkyzrhgrL7vYmbQ0mlVFe3tphT2lWbOV8fkGJlijMYMEHwxby6Qn4XTsxbYZD6CtakU","q":"3xNtcipbvk3RUDBgjoxhb1HzKvzNSDDTYGf0C2HNl9snjjvF4mp2CfTe7wRd7i7N5_R-zfB_KoZ6XH2aAKuCRiKb61wsHohG3QtJhMtqiSIG4jcuW1cqVt6X4uYSdPfYEcxI-kslTcfQ8ChycZDTaMxRORycgb-Xct5P1JFAVOc","qi":"H7sbm1Vp7BlX5gihmu5s4sA3H2nf-NyG6M01pYBcR5RpyaouwEQEVQK71JGm1VWt3jYfVQ79wNHzYZ6UYVOiLV-U4oFRXz2wAkQMjQvQrQrrdxujlgQ8hRj_S_6ogQnFnxAGd8onm2cdX1LZGoEPCfsEy1QLjUHs_fwCAcq1HNA","use":"enc"}'

Figure A.134

# Prepare subscription object including public key.  Put here your actual email address to receive notifications.

myobj = {
  "name": "pySubscription",
  "delivery": "mailto:john.doe@company.com" ,
  "schedule": "* * */1 * *",
  # "resources-uri": endpoint_items + '?f=xml',
  "resources-uri": endpoint_items,
  "expires": 1759104237,
  "sec-opts": {
    "x-ogc-callback-key": "string",
    "public-key": ce_key.export()
  }
}

myobj

Figure A.135

{'name': 'pySubscription',
 'delivery': 'mailto:john.doe@company.com',
 'schedule': '* * */1 * *',
 'resources-uri': 'https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items',
 'expires': 1759104237,
 'sec-opts': {'x-ogc-callback-key': 'string',
  'public-key': '{"d":"_rw1-M-daUJgW80IuhltH3uFpv0lttiSbeIa_A1Gn75mc48w3kaTXH0RHpC6whAz88N0fKxbJwDbmsUs6PJ1BvkZJTu04nOtlTF0GuWj7uhAY5S-zj-Gq5odBUyi72S8aSOpKMFOeiwcYZxWs-L4_attPMJSDgMxTzHtpTjmZvTSSESuD-KYkJPTbvvA7UVBIt43usuNTUhxDVcQY-emGTAYsicOeZGWFGWYo24LjX1RKP95IztCa0Mw2MPEPE8rA1muvfkk3MnhntdOLRTlw0TexpAwNGn0_2hy80uFwD6vRPOCzocLZT0FdllgOLYzr4JwXE_G1MIVIgTXnwZB","dp":"P60BtUnExG1zxR6obqGnP5z2yCGtp0LXjrg5tFJa6H6OPv_wALbPSfEf67Dj8IvQTmZnPDVmOT21GRbB2fV7LtqfHMpt0-bTMHlwBkR0BJo47BF0PHwnX_MtepHzvYA36roXkimS_8Oc_PR4DqPa0up3DbsO6Bid0xwBRkcYXCU","dq":"TQ466gqzsiLTQK3VTKg1J-zY4Gp-xocHHPALnrrj96aeHUWMb09zArFxKIMLpzDHs24DN0PxyVC2h6hjQAP-dheSYFRwcQOF5uj1NkfFvyTf19hTzP1pBKTTNm9exMSwAEXel4bJlfqFs89k6NGsFTEuhVnavf7eY7FjRfv-itU","e":"AQAB","kid":"clikid","kty":"RSA","n":"2qBsAlkltTmv-oMoLVsay9B-CAo_3ie5fi8Mg9Aph72w9uR5gEcfz6A-rsPLMH8buNwuUIoKo73NRc-glXBA9XUSvNn86dJiHTEyKAZm9ybm3_qZGSDl0KlgqDNx-qGOi2r5JSN3AQYlAvLi1_qSaIVDOwKQJY7NZR1C7Z2l7jqQfSxEoIRSt_K57Gt9wo7GIHcuOnzr30zTYg1UzSQx_b8bxdoUDWrNgCJYw9NuwmvRkjaBJr___bMbKz0LnqlwfI3eHqCYb8bfcR9YdL17f4vIAtkk_XWXjB-hldoPwQiVpBno4Bz14PXaDFB4p8d3BcrLwKz3ESy6sW6CiZmIQw","p":"-uTjBeriYAs1L11usnn1B763ki0flOK5Lcj_r2nFZ1-qwd52fZqSoIkSKJ06zPmIkYSuVDLzfzTP4mKj_NmWBakxmLAdR2jIsGQ8BU1IdkyzrhgrL7vYmbQ0mlVFe3tphT2lWbOV8fkGJlijMYMEHwxby6Qn4XTsxbYZD6CtakU","q":"3xNtcipbvk3RUDBgjoxhb1HzKvzNSDDTYGf0C2HNl9snjjvF4mp2CfTe7wRd7i7N5_R-zfB_KoZ6XH2aAKuCRiKb61wsHohG3QtJhMtqiSIG4jcuW1cqVt6X4uYSdPfYEcxI-kslTcfQ8ChycZDTaMxRORycgb-Xct5P1JFAVOc","qi":"H7sbm1Vp7BlX5gihmu5s4sA3H2nf-NyG6M01pYBcR5RpyaouwEQEVQK71JGm1VWt3jYfVQ79wNHzYZ6UYVOiLV-U4oFRXz2wAkQMjQvQrQrrdxujlgQ8hRj_S_6ogQnFnxAGd8onm2cdX1LZGoEPCfsEy1QLjUHs_fwCAcq1HNA","use":"enc"}'}}

Figure A.136

A.13.1.  Create subscription

Example: 5.1
> Create subscription.

response = requests.post(endpoint_subscriptions, json = myobj,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response

Figure A.137

<Response [201]>

Figure A.138

A.13.2.  Get list of subscriptions

Example: 5.2
> Get list of subscriptions.

response = requests.get(endpoint_subscriptions,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response.text

Figure A.139

'[{"id":212,"name":"pySubscription","delivery":"mailto:john.doe@company.com","schedule":"* * */1 * *","resources-uri":"https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items","expires":1759104237,"sec-opts":{"x-ogc-callback-key":"string","public-key":"{\\"d\\":\\"GTSwJzYovf79k7JB6gW3ziiTy_VnFHL2PFiVcTTRs_TnNEN0_AgoUPQZ0U2gKM1L2vTiNqbAg1Wzs3CYYf_TJGCELVbikG82x5Pum0yxN3UDHvHXESum8OKdjIuGhhOw1kWbAUD9-haQIKpMUnLy432IC3TLlZ-f1twS-0YQR3zk2qdtsiQF5rIqFps0bjjcJid4F9ifxTQqeeYhaAkdh-SBmO2kikwkA_g4PH3fQdfM57R4iuy32TF6u-uLT5p54qRuQ-wTDZ0B_vzpQZ7jVc6skNvuW-XNmTng2hY9mSaeLoKiOf74QZyIKBSywKgAresxKfVnBuEppQEvdZKbSQ\\",\\"dp\\":\\"YKPZt__yim_TNerZ0inwls-hmmsv4BKzKyZTN2cl7VN_ruw4YCPQXXO5S4CzmUW8NO5g0icih1UHDwTLddTx-4w7nSlMJIv8sY6r46dAKMHtYju1HtF3ayrJoT6M9J5Re4tnLZx0Ns-rLxndbwCzFgS3viJPeaYKZkMUvwRzhbE\\",\\"dq\\":\\"FhWIJ3UroDsWHsLJUlh5MCybYzLsDFt7i8k0qJGHaad_zqdplWl_jkgBI6OSQeZUufhyNhkHsd_jTe-8a8ONuDT_4EUXphdQbnNw0vVGZqVtzcL9Fa-bnNiwrHSlA8UnF-jiDXX65z6jDEHKWD2fM37z112lP8xoueLcti4FvQk\\",\\"e\\":\\"AQAB\\",\\"kid\\":\\"clikid\\",\\"kty\\":\\"RSA\\",\\"n\\":\\"tt88JhkKs-d7tZy7mZGcXMvIQs2UWdufE5K3BfQ-6vvyfI3eHoRKpCqlLVBmSCD39pyv8ML0n7r5ZWUPZpeMJtqaJ_YPMwUX1TBgfEKwcI3ZQguXZbfvPOnpbVBx7zgnPYsdYT-nSeIu19I7A_-3ex29NjIbNXW7l2xEu__a5lJCDZjhXRu0Oy8blZz28WY20lSC79W0FB-gKlaNM_zZvBMWanTGg3IxmZf_YldZjvli37UVzROdDbSdlK02s9FiDQFbyGmpp25BCx5wn76Jue79Lxmo4j_OXqOwkNYx-gTYXb1bNIC5SMz-OYRXmSZEO-rtoM53bk08UrEZ4Qsqpw\\",\\"p\\":\\"xprCRD94cvlh5wjgXQWX3z_KZGIl0fE5H4dAebeiRgtPmuI2RPmAb4UiuJ5cdi1JmjLgfOi1mp-8eOT3hyPJGF-eM_Y_uMe8jGnhKRxFjRf80oY_kRRT6NWCIKhfVDxaLk9uSo6uWnxxmL3PCeQc45jHfhkPG4v8T0rbfcUZDBk\\",\\"q\\":\\"67iL9zdUx744x9WkfNKeIUNb4pO7QjCxwH1u-sEf_J5_Vtt8ct6vcDit7oSqVr9mlE_klpEAnxYQQNXndpN9vRHZMb1JWNkUa5CQXFBxPLL39gbKKOOJG7KDTMWF8BR3SeFlKdyoqSyf5C746dFHl9rywTAOkdSpCf1F7BnYxL8\\",\\"qi\\":\\"h96KLTIDphk0opY3dWep1ooMDTLHdawJ_3B2jOamhUv_feoHkdH6VAxGQETm-5_PMcOijHDIpzsWlZ54C9JhXlw6vEDHsR3FQAvcVWyo6M4XdefwoC4FgTKwJT3GsU71bhK2Q-W-1oaCMDVsg6IIGDzbMx6c-MuGdvN2E4BFBvU\\",\\"use\\":\\"enc\\"}"},"state":"created","created":1666365527},{"id":213,"name":"pySubscription","delivery":"mailto:john.doe@company.com","schedule":"* * */1 * *","resources-uri":"https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items","expires":1759104237,"sec-opts":{"x-ogc-callback-key":"string","public-key":"{\\"d\\":\\"_rw1-M-daUJgW80IuhltH3uFpv0lttiSbeIa_A1Gn75mc48w3kaTXH0RHpC6whAz88N0fKxbJwDbmsUs6PJ1BvkZJTu04nOtlTF0GuWj7uhAY5S-zj-Gq5odBUyi72S8aSOpKMFOeiwcYZxWs-L4_attPMJSDgMxTzHtpTjmZvTSSESuD-KYkJPTbvvA7UVBIt43usuNTUhxDVcQY-emGTAYsicOeZGWFGWYo24LjX1RKP95IztCa0Mw2MPEPE8rA1muvfkk3MnhntdOLRTlw0TexpAwNGn0_2hy80uFwD6vRPOCzocLZT0FdllgOLYzr4JwXE_G1MIVIgTXnwZB\\",\\"dp\\":\\"P60BtUnExG1zxR6obqGnP5z2yCGtp0LXjrg5tFJa6H6OPv_wALbPSfEf67Dj8IvQTmZnPDVmOT21GRbB2fV7LtqfHMpt0-bTMHlwBkR0BJo47BF0PHwnX_MtepHzvYA36roXkimS_8Oc_PR4DqPa0up3DbsO6Bid0xwBRkcYXCU\\",\\"dq\\":\\"TQ466gqzsiLTQK3VTKg1J-zY4Gp-xocHHPALnrrj96aeHUWMb09zArFxKIMLpzDHs24DN0PxyVC2h6hjQAP-dheSYFRwcQOF5uj1NkfFvyTf19hTzP1pBKTTNm9exMSwAEXel4bJlfqFs89k6NGsFTEuhVnavf7eY7FjRfv-itU\\",\\"e\\":\\"AQAB\\",\\"kid\\":\\"clikid\\",\\"kty\\":\\"RSA\\",\\"n\\":\\"2qBsAlkltTmv-oMoLVsay9B-CAo_3ie5fi8Mg9Aph72w9uR5gEcfz6A-rsPLMH8buNwuUIoKo73NRc-glXBA9XUSvNn86dJiHTEyKAZm9ybm3_qZGSDl0KlgqDNx-qGOi2r5JSN3AQYlAvLi1_qSaIVDOwKQJY7NZR1C7Z2l7jqQfSxEoIRSt_K57Gt9wo7GIHcuOnzr30zTYg1UzSQx_b8bxdoUDWrNgCJYw9NuwmvRkjaBJr___bMbKz0LnqlwfI3eHqCYb8bfcR9YdL17f4vIAtkk_XWXjB-hldoPwQiVpBno4Bz14PXaDFB4p8d3BcrLwKz3ESy6sW6CiZmIQw\\",\\"p\\":\\"-uTjBeriYAs1L11usnn1B763ki0flOK5Lcj_r2nFZ1-qwd52fZqSoIkSKJ06zPmIkYSuVDLzfzTP4mKj_NmWBakxmLAdR2jIsGQ8BU1IdkyzrhgrL7vYmbQ0mlVFe3tphT2lWbOV8fkGJlijMYMEHwxby6Qn4XTsxbYZD6CtakU\\",\\"q\\":\\"3xNtcipbvk3RUDBgjoxhb1HzKvzNSDDTYGf0C2HNl9snjjvF4mp2CfTe7wRd7i7N5_R-zfB_KoZ6XH2aAKuCRiKb61wsHohG3QtJhMtqiSIG4jcuW1cqVt6X4uYSdPfYEcxI-kslTcfQ8ChycZDTaMxRORycgb-Xct5P1JFAVOc\\",\\"qi\\":\\"H7sbm1Vp7BlX5gihmu5s4sA3H2nf-NyG6M01pYBcR5RpyaouwEQEVQK71JGm1VWt3jYfVQ79wNHzYZ6UYVOiLV-U4oFRXz2wAkQMjQvQrQrrdxujlgQ8hRj_S_6ogQnFnxAGd8onm2cdX1LZGoEPCfsEy1QLjUHs_fwCAcq1HNA\\",\\"use\\":\\"enc\\"}"},"state":"created","created":1666365965}]\n'

Figure A.140

# extract first subscription id

data = json.loads(response.text)
id = data[0]['id']
id

Figure A.141

212

Figure A.142

A.13.3.  Get subscription status

Example: 5.3
> Get subscription status.

response = requests.get(endpoint_subscriptions + "/" + str(id),
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response.text

Figure A.143

'{"name":"pySubscription","delivery":"mailto:john.doe@company.com","schedule":"* * */1 * *","resources-uri":"https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items","expires":1759104237,"sec-opts":{"x-ogc-callback-key":"string","public-key":"{\\"d\\":\\"GTSwJzYovf79k7JB6gW3ziiTy_VnFHL2PFiVcTTRs_TnNEN0_AgoUPQZ0U2gKM1L2vTiNqbAg1Wzs3CYYf_TJGCELVbikG82x5Pum0yxN3UDHvHXESum8OKdjIuGhhOw1kWbAUD9-haQIKpMUnLy432IC3TLlZ-f1twS-0YQR3zk2qdtsiQF5rIqFps0bjjcJid4F9ifxTQqeeYhaAkdh-SBmO2kikwkA_g4PH3fQdfM57R4iuy32TF6u-uLT5p54qRuQ-wTDZ0B_vzpQZ7jVc6skNvuW-XNmTng2hY9mSaeLoKiOf74QZyIKBSywKgAresxKfVnBuEppQEvdZKbSQ\\",\\"dp\\":\\"YKPZt__yim_TNerZ0inwls-hmmsv4BKzKyZTN2cl7VN_ruw4YCPQXXO5S4CzmUW8NO5g0icih1UHDwTLddTx-4w7nSlMJIv8sY6r46dAKMHtYju1HtF3ayrJoT6M9J5Re4tnLZx0Ns-rLxndbwCzFgS3viJPeaYKZkMUvwRzhbE\\",\\"dq\\":\\"FhWIJ3UroDsWHsLJUlh5MCybYzLsDFt7i8k0qJGHaad_zqdplWl_jkgBI6OSQeZUufhyNhkHsd_jTe-8a8ONuDT_4EUXphdQbnNw0vVGZqVtzcL9Fa-bnNiwrHSlA8UnF-jiDXX65z6jDEHKWD2fM37z112lP8xoueLcti4FvQk\\",\\"e\\":\\"AQAB\\",\\"kid\\":\\"clikid\\",\\"kty\\":\\"RSA\\",\\"n\\":\\"tt88JhkKs-d7tZy7mZGcXMvIQs2UWdufE5K3BfQ-6vvyfI3eHoRKpCqlLVBmSCD39pyv8ML0n7r5ZWUPZpeMJtqaJ_YPMwUX1TBgfEKwcI3ZQguXZbfvPOnpbVBx7zgnPYsdYT-nSeIu19I7A_-3ex29NjIbNXW7l2xEu__a5lJCDZjhXRu0Oy8blZz28WY20lSC79W0FB-gKlaNM_zZvBMWanTGg3IxmZf_YldZjvli37UVzROdDbSdlK02s9FiDQFbyGmpp25BCx5wn76Jue79Lxmo4j_OXqOwkNYx-gTYXb1bNIC5SMz-OYRXmSZEO-rtoM53bk08UrEZ4Qsqpw\\",\\"p\\":\\"xprCRD94cvlh5wjgXQWX3z_KZGIl0fE5H4dAebeiRgtPmuI2RPmAb4UiuJ5cdi1JmjLgfOi1mp-8eOT3hyPJGF-eM_Y_uMe8jGnhKRxFjRf80oY_kRRT6NWCIKhfVDxaLk9uSo6uWnxxmL3PCeQc45jHfhkPG4v8T0rbfcUZDBk\\",\\"q\\":\\"67iL9zdUx744x9WkfNKeIUNb4pO7QjCxwH1u-sEf_J5_Vtt8ct6vcDit7oSqVr9mlE_klpEAnxYQQNXndpN9vRHZMb1JWNkUa5CQXFBxPLL39gbKKOOJG7KDTMWF8BR3SeFlKdyoqSyf5C746dFHl9rywTAOkdSpCf1F7BnYxL8\\",\\"qi\\":\\"h96KLTIDphk0opY3dWep1ooMDTLHdawJ_3B2jOamhUv_feoHkdH6VAxGQETm-5_PMcOijHDIpzsWlZ54C9JhXlw6vEDHsR3FQAvcVWyo6M4XdefwoC4FgTKwJT3GsU71bhK2Q-W-1oaCMDVsg6IIGDzbMx6c-MuGdvN2E4BFBvU\\",\\"use\\":\\"enc\\"}"},"state":"created","created":1666365527}\n'

Figure A.144

A.13.4.  Start this subscription

A subscription is started by updating its state to start''. State transitions needed are created'’ → approved'' → ready'’ → started''. State becomes approved'’ when the code'' received by email at creation time is used in the PATCH'’. Status becomes ``ready'’ when the resource-uri is available as well.

Example: 5.4
> Approve subscription (PATCH).

myobj = {
  # use here the code you received by email for this subscription id.
  "code": "578Z8C"
}

response = requests.patch(endpoint_subscriptions + "/" + str(id), json = myobj,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response

Figure A.145

<Response [400]>

Figure A.146

Example: 5.5
> Start subscription (PATCH).

Use PATCH to change the subscription from state ready'' → started'’.

myobj = {
  "state": "start"
}

response = requests.patch(endpoint_subscriptions + "/" + str(id), json = myobj,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response

Figure A.147

<Response [400]>

Figure A.148

Check that state is updated to ``start'’.

response = requests.get(endpoint_subscriptions + "/" + str(id),
    verify=bool(verify_ssl),
    headers={'Accept': 'application/json', 'Authorization':  'Bearer ' + access_token})

response.text

Figure A.149

'{"name":"pySubscription","delivery":"mailto:john.doe@company.com","schedule":"* * */1 * *","resources-uri":"https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items","expires":1759104237,"sec-opts":{"x-ogc-callback-key":"string","public-key":"{\\"d\\":\\"GTSwJzYovf79k7JB6gW3ziiTy_VnFHL2PFiVcTTRs_TnNEN0_AgoUPQZ0U2gKM1L2vTiNqbAg1Wzs3CYYf_TJGCELVbikG82x5Pum0yxN3UDHvHXESum8OKdjIuGhhOw1kWbAUD9-haQIKpMUnLy432IC3TLlZ-f1twS-0YQR3zk2qdtsiQF5rIqFps0bjjcJid4F9ifxTQqeeYhaAkdh-SBmO2kikwkA_g4PH3fQdfM57R4iuy32TF6u-uLT5p54qRuQ-wTDZ0B_vzpQZ7jVc6skNvuW-XNmTng2hY9mSaeLoKiOf74QZyIKBSywKgAresxKfVnBuEppQEvdZKbSQ\\",\\"dp\\":\\"YKPZt__yim_TNerZ0inwls-hmmsv4BKzKyZTN2cl7VN_ruw4YCPQXXO5S4CzmUW8NO5g0icih1UHDwTLddTx-4w7nSlMJIv8sY6r46dAKMHtYju1HtF3ayrJoT6M9J5Re4tnLZx0Ns-rLxndbwCzFgS3viJPeaYKZkMUvwRzhbE\\",\\"dq\\":\\"FhWIJ3UroDsWHsLJUlh5MCybYzLsDFt7i8k0qJGHaad_zqdplWl_jkgBI6OSQeZUufhyNhkHsd_jTe-8a8ONuDT_4EUXphdQbnNw0vVGZqVtzcL9Fa-bnNiwrHSlA8UnF-jiDXX65z6jDEHKWD2fM37z112lP8xoueLcti4FvQk\\",\\"e\\":\\"AQAB\\",\\"kid\\":\\"clikid\\",\\"kty\\":\\"RSA\\",\\"n\\":\\"tt88JhkKs-d7tZy7mZGcXMvIQs2UWdufE5K3BfQ-6vvyfI3eHoRKpCqlLVBmSCD39pyv8ML0n7r5ZWUPZpeMJtqaJ_YPMwUX1TBgfEKwcI3ZQguXZbfvPOnpbVBx7zgnPYsdYT-nSeIu19I7A_-3ex29NjIbNXW7l2xEu__a5lJCDZjhXRu0Oy8blZz28WY20lSC79W0FB-gKlaNM_zZvBMWanTGg3IxmZf_YldZjvli37UVzROdDbSdlK02s9FiDQFbyGmpp25BCx5wn76Jue79Lxmo4j_OXqOwkNYx-gTYXb1bNIC5SMz-OYRXmSZEO-rtoM53bk08UrEZ4Qsqpw\\",\\"p\\":\\"xprCRD94cvlh5wjgXQWX3z_KZGIl0fE5H4dAebeiRgtPmuI2RPmAb4UiuJ5cdi1JmjLgfOi1mp-8eOT3hyPJGF-eM_Y_uMe8jGnhKRxFjRf80oY_kRRT6NWCIKhfVDxaLk9uSo6uWnxxmL3PCeQc45jHfhkPG4v8T0rbfcUZDBk\\",\\"q\\":\\"67iL9zdUx744x9WkfNKeIUNb4pO7QjCxwH1u-sEf_J5_Vtt8ct6vcDit7oSqVr9mlE_klpEAnxYQQNXndpN9vRHZMb1JWNkUa5CQXFBxPLL39gbKKOOJG7KDTMWF8BR3SeFlKdyoqSyf5C746dFHl9rywTAOkdSpCf1F7BnYxL8\\",\\"qi\\":\\"h96KLTIDphk0opY3dWep1ooMDTLHdawJ_3B2jOamhUv_feoHkdH6VAxGQETm-5_PMcOijHDIpzsWlZ54C9JhXlw6vEDHsR3FQAvcVWyo6M4XdefwoC4FgTKwJT3GsU71bhK2Q-W-1oaCMDVsg6IIGDzbMx6c-MuGdvN2E4BFBvU\\",\\"use\\":\\"enc\\"}"},"state":"created","created":1666365527}\n'

Figure A.150

A.13.5.  Delete the subscription

Example: 5.6
> Remove subscription (DELETE).

# id = 170

response = requests.delete(endpoint_subscriptions + "/" + str(id),
    verify=bool(verify_ssl),
    headers={'Authorization':  'Bearer ' + access_token})

response

Figure A.151

<Response [204]>

Figure A.152

A.13.6.  Get updated subscription list

response = requests.get(endpoint_subscriptions,
    verify=bool(verify_ssl),
    headers={'Accept': 'application/dcs+geo', 'Authorization':  'Bearer ' + access_token})

response.text

Figure A.153

'[{"id":213,"name":"pySubscription","delivery":"mailto:john.doe@company.com","schedule":"* * */1 * *","resources-uri":"https://ogc.demo.secure-dimensions.de/pycsw/collections/metadata:main/items","expires":1759104237,"sec-opts":{"x-ogc-callback-key":"string","public-key":"{\\"d\\":\\"_rw1-M-daUJgW80IuhltH3uFpv0lttiSbeIa_A1Gn75mc48w3kaTXH0RHpC6whAz88N0fKxbJwDbmsUs6PJ1BvkZJTu04nOtlTF0GuWj7uhAY5S-zj-Gq5odBUyi72S8aSOpKMFOeiwcYZxWs-L4_attPMJSDgMxTzHtpTjmZvTSSESuD-KYkJPTbvvA7UVBIt43usuNTUhxDVcQY-emGTAYsicOeZGWFGWYo24LjX1RKP95IztCa0Mw2MPEPE8rA1muvfkk3MnhntdOLRTlw0TexpAwNGn0_2hy80uFwD6vRPOCzocLZT0FdllgOLYzr4JwXE_G1MIVIgTXnwZB\\",\\"dp\\":\\"P60BtUnExG1zxR6obqGnP5z2yCGtp0LXjrg5tFJa6H6OPv_wALbPSfEf67Dj8IvQTmZnPDVmOT21GRbB2fV7LtqfHMpt0-bTMHlwBkR0BJo47BF0PHwnX_MtepHzvYA36roXkimS_8Oc_PR4DqPa0up3DbsO6Bid0xwBRkcYXCU\\",\\"dq\\":\\"TQ466gqzsiLTQK3VTKg1J-zY4Gp-xocHHPALnrrj96aeHUWMb09zArFxKIMLpzDHs24DN0PxyVC2h6hjQAP-dheSYFRwcQOF5uj1NkfFvyTf19hTzP1pBKTTNm9exMSwAEXel4bJlfqFs89k6NGsFTEuhVnavf7eY7FjRfv-itU\\",\\"e\\":\\"AQAB\\",\\"kid\\":\\"clikid\\",\\"kty\\":\\"RSA\\",\\"n\\":\\"2qBsAlkltTmv-oMoLVsay9B-CAo_3ie5fi8Mg9Aph72w9uR5gEcfz6A-rsPLMH8buNwuUIoKo73NRc-glXBA9XUSvNn86dJiHTEyKAZm9ybm3_qZGSDl0KlgqDNx-qGOi2r5JSN3AQYlAvLi1_qSaIVDOwKQJY7NZR1C7Z2l7jqQfSxEoIRSt_K57Gt9wo7GIHcuOnzr30zTYg1UzSQx_b8bxdoUDWrNgCJYw9NuwmvRkjaBJr___bMbKz0LnqlwfI3eHqCYb8bfcR9YdL17f4vIAtkk_XWXjB-hldoPwQiVpBno4Bz14PXaDFB4p8d3BcrLwKz3ESy6sW6CiZmIQw\\",\\"p\\":\\"-uTjBeriYAs1L11usnn1B763ki0flOK5Lcj_r2nFZ1-qwd52fZqSoIkSKJ06zPmIkYSuVDLzfzTP4mKj_NmWBakxmLAdR2jIsGQ8BU1IdkyzrhgrL7vYmbQ0mlVFe3tphT2lWbOV8fkGJlijMYMEHwxby6Qn4XTsxbYZD6CtakU\\",\\"q\\":\\"3xNtcipbvk3RUDBgjoxhb1HzKvzNSDDTYGf0C2HNl9snjjvF4mp2CfTe7wRd7i7N5_R-zfB_KoZ6XH2aAKuCRiKb61wsHohG3QtJhMtqiSIG4jcuW1cqVt6X4uYSdPfYEcxI-kslTcfQ8ChycZDTaMxRORycgb-Xct5P1JFAVOc\\",\\"qi\\":\\"H7sbm1Vp7BlX5gihmu5s4sA3H2nf-NyG6M01pYBcR5RpyaouwEQEVQK71JGm1VWt3jYfVQ79wNHzYZ6UYVOiLV-U4oFRXz2wAkQMjQvQrQrrdxujlgQ8hRj_S_6ogQnFnxAGd8onm2cdX1LZGoEPCfsEy1QLjUHs_fwCAcq1HNA\\",\\"use\\":\\"enc\\"}"},"state":"created","created":1666365965}]\n'

Figure A.154


Annex B
(informative)
Revision History

Date Release Author Primary clauses modified Description
2022-06-02 0.1 Y. Coene all Initial draft version
2022-10-21 0.8 Y. Coene all Version addressing review comments from Carl Reed and agentschap Digitaal Vlaanderen.

Bibliography

[1]  OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP), IETF draft, 2022 : https://datatracker.ietf.org/doc/html/draft-ietf-oauth-dpop-11

[2]  OAuth 2.0 Security Best Current Practice, IETF draft, 2022 : https://www.ietf.org/archive/id/draft-ietf-oauth-security-topics-20.txt

[3]  IOC TF: Technical Guidance for INSPIRE Discovery Services, IOC Task Force for Network Services, Issue 3.1.1, 2011, https://inspire.ec.europa.eu/documents/technical-guidance-implementation-inspire-discovery-services-0

[4]  INSPIRE MIG: Technical Guidance for the implementation of INSPIRE dataset and service metadata based on ISO/TS 19139:2007, 2017 https://inspire.ec.europa.eu/id/document/tg/metadata-iso19139

[5]  INFORMATIE VLAANDEREN: Richtlijn GDI-Vlaanderen Best Practices voor Metadata V2.0, 2020 https://www.geopunt.be/~/media/geopunt/geowijzer/metadata/documenten/aan_de_slag_2020/gdi_vl_bestpractices_v0_18.pdf

[6]  Geonovum: Nederlands metadata profiel op ISO 19115 voor geografie versie 2.1.0, 2020 https://docs.geostandaarden.nl/md/mdprofiel-iso19115

[7]  IETF: JWS Clear Text JSON Signature Option (JWS/CT), 2022 https://www.ietf.org/id/draft-jordan-jws-ct-08.html

[8]  OGC: INSPIRE and OGC APIs — Part 1: Modernising INSPIRE — https://www.ogc.org/blog/4603.