Relayed Archive API

Relayed Archive developed for OpusCapita Invoice Sending clients to search invoices via API stored to OpusCapita Archive. The solutions can be also used to download invoices from the archive with high level of security. Relayed Archive is an additional feature to the OpusCapita Archive solution available in the Business Network Portal application.

Relayed Archive is available for sales invoice archive only.


Client, a customer of OpusCapita using invoice archive.​

Customer, a customer of the OC client, receiving invoices directly or indirectly via OpusCapita Business Network. These end users are not known or identified by OC.​

Archive, invoice storage offered by OpusCapita.​

JWT token, JSON Web Token is a standard method for representing claims securely between two parties. Contains signature generated e.g. in jwt.io​

BNP, online service (Business Network Portal) from OpusCapita for suppliers and buyers to transact P2P messages, monitor transactions processing and archive invoices.​

Customer portal, online service hosted by the client including user authentication and company identification.​

Customer number, unique identifier assigned by the client for all of its customers.​


Relayed Archive API

As a customer, you should use OpusCapita endpoint to access Relayed Archive solution. We offer piloting, test and production API for customer use:

 

If you are using a legacy archive solution from OpusCapita (such as Document Forwarding or Relayed Trust Archive), you should update the endpoint to use above API’s.

  • Relayed Archive allows OpusCapita clients to grant access to their customers to download their own invoices with a high level of security. Relayed Archive is an addition to the OpusCapita eArchive solution available in the Business Network Portal application.​

  • Client is required to generate a JWT and it is used while end user is requesting via in the customer portal (HTTP GET) to download an invoice from the archive.

 

Authentication - JWT Token

When sending a request to Relayed Archive API, all search values should be sent in a JWT token. This ensures high security as confidential values are encrypted.

Content of the token

Token requires authorization header to enter to the Business Network gateway​. Payload will be extracted by exchanging key values between customer and OpusCapita. Payload contains all necessary information to identify you as an Archive customer, and the search values to find individual invoices from the Archive. Signature is required in the token to verify the message wasn't changed along the way. It can be encrypted with chosen algorithm e.g. HMAC SHA256. Public key must be provided to OpusCapita to decrypt the signature. The public key must an expiration date and customer is responsible to share a new key. JWKS URL is hosted on the customer side and contains the public keys. 

Token structure:​

  • HEADER​

  • PAYLOAD​

  • SIGNATURE​

Token PAYLOAD content (mandatory):​

json field

necessity

Name

Description

json field

necessity

Name

Description

businessPartnerId

semi-optional*

Business partner id

OC generated unique id for the client, it need to be a child unit in the structure of iss or the iss itself to assure privacy policy is not going to breach

customerNumber

optional*

Customer number

Client generated unique id for the customer

invoiceNumber

optional

Invoice number

Invoice number as generated by the client​

iss

mandatory

Issuer

Identifies the principal issuing the JWT, can be a string or URI, in this case it need to be OC generated unique id for the client that is the parent unit for businessPartnerId or the businessPartnerId itself

We can configure this to be any string (though it is better to avoid special characters like \000).

Example values can be:

- business partner ID of the OpusCapita registered company issuing the certificate, ex “myCompany123”

- a well understood company name, ex. “OpusCapita Solutions Oy”

- an URL pointing the organization or public certificate, ex. “example.com” or “https://businessnetwork.opuscapita.com/auth/certs

For simplicity and consistency it is probably best to use business partner id - this was implemented in the current version of code.

aud

mandatory

(currently ignored)

Audience

Specifies the token target recipient, ie. OpusCapita Archive

This could be any string though domain name might be a reliable option.

It is formally required by rfc7519 though currently ignored by OpusCapita.

iat

optional

Issued at time

Time when the JWT was created​

exp

optional

Expiration time

Time how long the JWT is valid​

sub

optional

Subject

Optional subject claim, ex. archive

It must match the configured value on OpusCapita side.

 

Creating JWT

There are different types of free tools to generate JWT tokens, depending on you preferred programming language. In order to use the token payload, there must be an encrypted keys exchanged between OpusCapita and customer.

  1. First you must generate keys. These are used for generating JWT token. You should create private or public keys.

    1. Private key (symetric): Use secret known by OC and you as a customer.

    2. Public key (asymetric): Create own public key and share it via endpoint which OC can fetch and cache. Please share also the expiration time of the public key.

  2. Send one token per request. Single document download requires a separate JWT token.

  3. Generate token. Token payload content in chapter https://opuscapita.atlassian.net/wiki/spaces/HTUCSP/pages/12434014250/Relayed+Archive+API#JWT-Token

  4. Encrypt the token content with chosen algorithm. For example ES512 or RS512.

openssl genpkey -algorithm RSA -out private-key.pem openssl pkey -pubout -in private-key.pem > public-key.pem cat public-key.pem | npx pem-jwk > public-key.jwk echo "[$(cat public-key.jwk)]" > public-keyset.jwks

Validate / test your token

You can test your generated token content here: https://jwt.io/

Token decoded version should have following content:

 

Relayed Archive gateway

Please see the technical specification here:

Stage (test) environment: https://api.stage.businessnetwork.opuscapita.com/relayed-archive/api/docs/

Production environment: https://api.businessnetwork.opuscapita.com/relayed-archive/api/docs/

Connect to gateway

OpusCapita has an open api-gateway which you need to send a request to the gateway with the token. It is recommended to test with OpusCapita by using the development or stage environment. After acceptance testing customers can start using the production environment.

Specific token request: Token contains all required values including invoice number and is sent to a generic endpoint: http://api.develop.businessnetwork.opuscapita.com/relayed-archive

[alternative] Generic token request: the token contains only businessPartnerId and Customer number, but the gateway URL can contain the invoice number specifying to which invoices the token relates to http://api.develop.businessnetwork.opuscapita.com/relayed-archive/invoice/<invoiceNumber>

Gateway response

Once the token is received and decrypted, the API returns single invoice image. The service can response with following values:

Code

Description

Code

Description

200

Successfully fetched invoice image

401

Authentication on API gateway failed

403

Some of the required invoice parameters are missing or JWT was not present

404

Fetching the invoice failed for various reason

  • Wrong “sub” (subject “dummy” where “test” was configured on OpusCapita side)

    • 403 RBAC: access denied

    • We can configure whatever subject - usually “test” or “archive” or can match any

  • Wrong "iss" (issuer “dummy” where “bnpautomationsupplier” or other supported value was expected)

    • 401 Jwt issuer is not configured

  • Document not found (invoiceNumber cannot be found as “x” was added at the end of invoice number)

    • 404 No document found in archive for businessPartnerId: bnpautomationsupplier, customerNumber: cust123, invoiceNumber: Test_Invoice_Number_17_01_53422x

  • Unauthorized access (trying to escalate access to fetch documents of another company that I am not authorized to access)

    • 403 You have no permissions to access the requested resource.

  • Hacking with "none" algorithm (“none” can be used to bypass token validation)

    • 401 Jwt is not in the form of Header.Payload.Signature with two dots and 3 sections

  • Better hacking with "none" (same as above but bypassing format validation)

    • 401 Jwt header [alg] is not supported

    • "alg": "none" is not supported for security reasons

  • Invalid value (not BASE64)

    • 401 Jwt header is an invalid Base64url encoded

    • Some servers can fail if very long URL is used - here header is parsed but was not a valid BASE64 string (wrong number of characters)

  • Not a JSON

    • 401 Jwt header is an invalid JSON

    • token was passed to a server which tried to decode it (it can be sometimes abused for DoS)

  • Too long value

    • 431

    • Trying to send a properly signed token with custom value in the header but with very long value (can we get a buffer overflow?)

  • Extended but correct request (extra field)

    • 200

    • Token had extra field in the header and was properly signed → everything works fine and unknown fields are ignored (works but you never know if same field would be in use in the future)

  • Wrong iat (issued at in the future)

    • 200

    • IAT is in the future but we ignore it currently

  • Expired token

    • 401 Jwt is expired


Example keys, tokens and requests:

  • RSA 2048 (least secure) with SHA256 = RS256, token and example request

    • private key (PEM format)

      -----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA5sFMdgNmhIiMiX2W6p4eDHZkyC7rxepHWEVKOEYtztu7DKEa V/vYQ36+++8JQ9J0Vzjw/jBcKid5eV9urKTQmnuaW6IzZlTMpL9vwldjGr2DjwCk CJbt+81+hOQpyzCveR41xmSXxXbQCQx70gUyciaoonCxRbebBGmrBjTGKFCdntRI 32i8IkXmADyMQIPWr3zQmawNkO7H5ne4OoH7Lz7k0SuPoJGE2tSCg44tz19YHX3u QIM+8+VdouCMsfNyWO73geonS4YTP0GDFqX4cgEfk1l5iqpeW2UuODi59cBlw+uT oEk8eIGioVMBytbSy7XbTIO2BonH9vyrktBtoQIDAQABAoIBAGVoc3K1gdsiqyhN EgKfZDMz4Ix82k6K67mmEbzzUnRC6kvdjNc3rU3UKJhM7zRoC4q9UmNS214HJQIq 51dlwurxAN/eQ1poT9ri6nlsr/fzaxpwPKYttf5fy4cZQiiyh5rhpN5AHNbBpSEk 5FFiyU2TIa7peW5bBvwEeA1tKdxS44KbS2I2c6TdR6lBOXtkzrsMDirorjXZ4SJI 3WdForF6GPuOwEA3dAPEm7C6RGOwUd9kLhxcTz2b6lwzdwwGq2bxgSe39whxd4Ev vnwrFmRZCG3LQDxxqvmA08ea1KctHutA+Py+RIADZrXT0uZBeiUhu/nQCRmUvgWT TpmnTBUCgYEA+2jURsZ0K/2/R4sOIuH0dldvLWi4mkRLszE04+FChhLoQvWJwXGn RAr+GkQbwrwjn+vQTknZh4Q1MR2W54BEgD4HCokrHfd32njglrqbfDCt7yarz3g4 +STAfZHVifN/Yx5LZ6HCQUgPZS6vPaHJmEvihuZUHOeRh/sVzxdzo+MCgYEA6vfs hkZpuYZs5AhlHUA/V6uE2WTjZ8r18wKOYFVqo3RqziTXPII0JFJukRZ/ZQEu42dt T7+IQSyoczOcsGg3o69B13fcWmpMmjAdbSNYMXjAGBJEPtoQRCDuJtHdbg0QgSeh id57Tu9Y393nAHyHpbnJ/KDi0cDnPaAteHfKR6sCgYBHdLUY5KDyO+3Y5MIA0h4M YK99xYzqc8zcQnkY59Zjiw4useEUdTwoT8OHLaKCR70MYBbVmZHVPZNswU85vzA5 Dugra28w1jxfgQm8bY9xzdgx59jfX/k5fuOjDQcXbXjgcCTYcJZovZV6mbk/GDPX MIJS+zYe/QZVEt1Q/gZlJwKBgFnltRbChdy3c53jIFyKojF2rANIuECTxHnPNo3g 4EXdWqe4LKk3358t8qOMCf2o8DmM7qOeUhEtdt1sl7xegzsa6IP5ldL57Ijpc7i3 1xxGaKhNBNNPNv3542Py01cxpGjlssY+2sqehFBSY/kpq/RaGs+O9njt5wsK55q5 qii1AoGAP/tVx4GVsCmJLpmXjg3uCGmFllfgXXtUD3ZZoV0gqq2135tvNO/f4qO7 RJ5fC3XriXam8D6F/9F9Dll78/M44YxwPxgQbyrY+VSro5nVQ4q2ZcoQlbrn3FXt bCiDymfFyJw02zy8nL1+NVfK5iRstYPkLqQeZO/66tMevr52Cvc= -----END RSA PRIVATE KEY-----
  • RSA 4096 (most compatible) with SHA512 = RS512, token and example request

  • ES256 (small yet secure, commonly used) token and example request

  • ES384 (more secure than ES384) token and example request

  • ES512 (most secure, often not supported by tools) token and example request

Example requests pass the token in the query parameter https://api.develop.businessnetwork.opuscapita.com/relayed-archive?token=... but the token can be also passed as a request header (recommended): curl https://api.develop.businessnetwork.opuscapita.com/relayed-archive -H 'Authorization: Bearer ...' where ... is replaced with the token.


end of document