Signature Service
- 1 Signature Service Overview
- 2 Signature Types
- 3 QR Code Signing
- 4 Methods in the Signature Service
- 4.1 Initiate Sign Method
- 4.1.1 JSON Example for initSignRequest
- 4.1.2 EMAIL userInfoType Example Request
- 4.1.3 PHONE userInfoType Example Request
- 4.1.4 SSN userInfoType Example Request
- 4.1.5 UPI userInfoType Example Request
- 4.1.6 Possible Errors
- 4.1.7 JSON Response Value
- 4.1.8 JSON Response Value if useDynamicQrCode is set to TRUE
- 4.2 Get One Signature Result Method
- 4.2.1 JSON Example for getOneSignResultRequest
- 4.2.2 Example Request
- 4.2.3 Possible Errors
- 4.2.4 JSON Response Value
- 4.2.4.1 details
- 4.3 Get Signature Results Method
- 4.3.1 JSON Example for getSignResultsRequest
- 4.3.2 Example Request
- 4.3.3 Possible Errors
- 4.3.4 JSON Response Value
- 4.4 Cancel Sign Method
- 4.4.1 JSON Example for cancelSignRequest
- 4.4.2 Example Request
- 4.4.3 Possible Errors
- 4.1 Initiate Sign Method
Signature Service Overview
The Freja Signature Service allows Relying Parties to securely deliver messages to a user, as well as to prompt Freja end users to digitally sign data and documents.
This is available to all Freja users regardless of registration level, provided they have registered a Freja account with an email at least. Signatures created by the end users are PKI-based and therefore non-repudiable.
The signature flow is practically identical to authentication described in Authentication Service. The main difference is that while simultaneous authentication requests are not possible and are limited to 2 minutes, a user may have multiple signature requests pending for up to 30 days.
This allows for flexible signing solutions to be built on top of Freja where users can be prompted to sign even outside a direct online context.
Signature Types
Freja eID allows for several types of signatures.
Simple Signatures
The Simple signature type allows signing of UTF-8 text. Upon completion of the signature by the user, the Relying Party receives a JWS structure containing the data that was presented to the user, as well as evidence that the Freja eID infrastructure has validated the signature.
Extended Signatures
The extended signature type allows signing of UTF-8 text (presented to the user) alongside binary data (not presented to the user). Upon completion of the signature by the user, the Relying Party receives a JWS structure containing the data that was presented to the user and the supplied binary data, as well as evidence that the Freja eID infrastructure has validated the signature.
Advanced Signatures
The advanced signature type allows signing of UTF-8 text (presented to the user), binary data (not presented to the user) or both with one-time certificates tied to the end-user's personal data and that can be validated independently outside Freja. Note that no revocation data is supplied for the signing certificates as they are generated under user consent for one-time usage and are implicitly valid at the time of signing. The advanced signature is returned as part of the ordinary response signed by Freja eID. Currently supported advanced signature formats are listed in the table below:
Data Type | Signature Format | Value Returned to Relying Party |
|---|---|---|
SIMPLE_UTF8_TEXT | XML_MINAMEDDELANDEN | An enveloping XML signature suitable for electronic mailbox services that integrate with Tekniska tjänstekontrakt-API Mina meddelanden |
QR Code Signing
QR code signing is supported by the Freja eID Signature service. In essence, a user signs transaction by scanning a generated QR code and approving the signature action.
On mobile the process is even simpler since the user does not need to scan a QR code physically. Everything takes place within their device thereby making signatures even more secure because the process is initiated and approved on the same device. In addition, this method is the most user friendly since it foregoes typing in user identifiers (emails, phone numbers, social security number etc.).
In summary, we recommend implementing QR code signing because:
It is much more user friendly, especially on mobile.
It is a much safer method of signing.
This document goes more into depth regarding the Freja eID API. If you would like to see more details QR code login implementation, please refer to this page about Implementation and Best Practices.
Dynamic QR Code Implementation
If you would like more information about implementing dynamic QR codes, refer to this dedicated page about Dynamic QR Code Implementation.
Don’t Forget
There are several technical requirements that must be in place before implementation can begin. Please refer to the section 'Before You Begin' on this page.
Methods in the Signature Service
The Freja eID Relying Party Signature Service allows you to:
Initiate a signature request;
Get one signature result;
Get multiple signature results;
Cancel a signature request.
When it comes to getting signature results, we recommend using the method for multiple results to reduce the number of polling requests.
Initiate Sign Method
This method is used by a Relying Party to initiate a sign transaction. This method is intended for creating signatures both in online contexts, where the access to the Relying Party's service or application is initiated by the end user, as well as in offline contexts, where the signature request is initiated by the Relying Party's service in its own right. Signature transactions, therefore, have configurable longevity — from the point of initiation, the user has between two minutes and 30 days to confirm the signature request. As opposed to authentication requests, multiple signature requests may be active at any given time, from the same or different Relying Parties.
Although in most cases possession and control of the handheld device on which a Freja mobile application is installed are sufficient for allowing the user to view transaction content when initiating a transaction, a Relying Party can also specify whether the content is confidential or not. The confidentiality flag governs whether the user must enter their PIN or, if enabled, use one of the biometric authentication alternatives on the handheld device, before being allowed to view the content of the transaction. The option effectively provides an option to have transactions that are "signed-for (for viewing) with explicit consent (for accepting the content)".
The method is called using HTTP POST through the URLs below:
Environment | Endpoint |
|---|---|
TEST |
|
PRODUCTION |
|
JSON Example for initSignRequest
The parameter of the method is a Base64 UTF8-encoded JSON payload according to the following:
{
"userInfoType":"User info type",
"userInfo":"User information corresponding to user info type",
"minRegistrationLevel":"Minimum required registration level of a user",
"userConfirmationMethod":"Method used to confirm user's identity",
"useDynamicQrCode":"Flag to enable dynamic QR code",
"title":"Title to display in transaction list",
"pushNotification":{
"title":"Title to display in push notification to user",
"text":"Text to display in push notification to user"
},
"expiry":"Expiry time for the request",
"dataToSignType":"Type of data to sign",
"dataToSign":"The data to be signed",
"signatureType":"Signature type",
"attributesToReturn":[
{
"attribute":"Type of attribute to be returned"
}
]
} |
|
Inferred transactions are not bound to a specific user upon initiation, they are bound to a user when a QR code is scanned. That is, the first user that scans the QR code of a pending inferred transaction gets bound to it. As such you need to be aware of the privacy of the content contained in signature request: if the content is sensitive and intended for a specific recipient we strongly advise you to use one of the binding forms of the signature API. | |
For userInfoType set to PHONE, the value must be in the following format: "+4673*******"; the leading '+' sign is present, but the leading '0' for the mobile phone operator code is not. | |
{
"country":"Country of SSN",
"ssn":"Social security number of the end user"
}Where:
| |
Concerning minRegistrationLevel When set to INFERRED, the transaction can proceed without enforcing a specific registration level. Instead, the system will infer and use the user's actual registration level at runtime. The set of returned attributes will vary based on the user's actual level. For example, if the BASIC_USER_INFO attribute is requested and the user is at the BASIC level, the attribute will not be returned (null), as it is not available at that level. If the user is at EXTENDED or PLUS, the attribute will be included in the response. In order to be able to use INFERRED as the minimal registration level, you must first get in touch with partnersupport@frejaeid.com. | |
| |
| |
| |
| |
| |
| |
{
"text":"Base64 encoded UTF-8 text displayed to the end user"
}text: string, mandatory, 4096 plain text characters maximum prior to Base64 encoding. The text that will be shown in the mobile application and signed by the end user. The content of the Base64 string are bytes representing a UTF-8 encoding of the text to be displayed to and signed by the user. | |
{
"text":"Base64 encoded UTF-8 text displayed to the end user"
"binaryData":"Base64 encoded byte array not displayed to the user"
}text: string, mandatory, 4096 plain text characters maximum prior to Base64 encoding. The text that will be shown in the mobile application and signed by the end user. The content of the Base64 string are bytes representing a UTF-8 encoding of the text to be displayed to and signed by the user. binaryData: string, mandatory, 5 MB maximum prior to Base64 encoding. This is not shown to the user in the mobile application but is, nonetheless included in the signature. | |
| |
The following attributes: BASIC_USER_INFO, DATE_OF_BIRTH, AGE, PHOTO, ADDRESSES, SSN, DOCUMENT or DOCUMENT_PHOTO are not available for BASIC users. |
EMAIL userInfoType Example Request
If you wish to initiate a signature request for a user with an email address joe.black@freja.com, follow these steps:
Create the JSON structure {"userInfoType":"EMAIL","userInfo":"joe.black@freja.com","minRegistrationLevel":"BASIC","title":"Sign transaction","expiry":1517526000000,"dataToSignType":"SIMPLE_UTF8_TEXT","dataToSign":{"text":"VGhpcyBpcyBhIHRleHQgZm9yIHNpZ24gdHJhbnNhY3Rpb24u"},"signatureType":"SIMPLE","attributesToReturn":[{"attribute":"CUSTOM_IDENTIFIER"}]}
Encode the JSON structure to Base64.
Create the HTTP POST request with a POST parameter name initSignRequest and the Base64 encoded JSON structure from the step 2 as its value.
The HTTP body should be the following (compact format, line broken for clarity only):
initSignRequest=eyJ1c2VySW5mb1R5cGUiOiJFTUFJTCIsInVzZXJJbmZvIjoiam9lLmJsYWNrQH
ZlcmlzZWMuY29tIiwibWluUmVnaXN0cmF0aW9uTGV2ZWwiOiJCQVNJQyIsInRpdGxlIjoiU2lnbiB0
cmFuc2FjdGlvbiIsImV4cGlyeSI6MTUxNzUyNjAwMDAwMCwiZGF0YVRvU2lnblR5cGUiOiJTSU1QTE
VfVVRGOF9URVhUIiwiZGF0YVRvU2lnbiI6eyJ0ZXh0IjoiVkdocGN5QnBjeUJoSUhSbGVIUWdabTl5
SUhOcFoyNGdkSEpoYm5OaFkzUnBiMjR1In0sInNpZ25hdHVyZVR5cGUiOiJTSU1QTEUiLCJhdHRyaW
J1dGVzVG9SZXR1cm4iOlt7ImF0dHJpYnV0ZSI6IkNVU1RPTV9JREVOVElGSUVSIn1dfQ==PHONE userInfoType Example Request
If you wish to initiate a sign request for a user with a phone number '+46731234567':
Create the JSON structure {"userInfoType":"PHONE","userInfo":"+46731234567","minRegistrationLevel":"BASIC","title":"Sign transaction","confidential":false,"expiry":1517526000000,"dataToSignType":"SIMPLE_UTF8_TEXT","dataToSign":{"text":"VGhpcyBpcyBhIHRleHQgZm9yIHNpZ24gdHJhbnNhY3Rpb24u"},"signatureType":"SIMPLE"}
Encode the JSON structure to Base64.
Create the HTTP POST request with a POST parameter name initSignRequest and the Base64 encoded JSON structure from the step 2 as its value.
The HTTP body should be the following (compact format, line broken for clarity only):
initSignRequest=eyJ1c2VySW5mb1R5cGUiOiJQSE9ORSIsInVzZXJJbmZvIjoiKzQ2NzMxMjM0NT
Y3IiwibWluUmVnaXN0cmF0aW9uTGV2ZWwiOiJCQVNJQyIsInRpdGxlIjoiU2lnbiB0cmFuc2FjdGlv
biIsImNvbmZpZGVudGlhbCI6ZmFsc2UsImV4cGlyeSI6MTUxNzUyNjAwMDAwMCwiZGF0YVRvU2lnbl
R5cGUiOiJTSU1QTEVfVVRGOF9URVhUIiwiZGF0YVRvU2lnbiI6eyJ0ZXh0IjoiVkdocGN5QnBjeUJo
SUhSbGVIUWdabTl5SUhOcFoyNGdkSEpoYm5OaFkzUnBiMjR1In0sInNpZ25hdHVyZVR5cGUiOiJTSU
1QTEUifQ==SSN userInfoType Example Request
If you wish to initiate a sign request for a user with an SSN '198905218072' and country 'SE':
Create the JSON structure {"country":"SE","ssn":"198905218072"}, then do the base64 of this JSON.
This is the Base64 of step 1: 'eyJjb3VudHJ5IjoiU0UiLCJzc24iOiIxOTg5MDUyMTgwNzIifQ==' , which is the userInfo value in our request.
Create the JSON structure {"userInfoType":"SSN","userInfo":"eyJjb3VudHJ5IjoiU0UiLCJzc24iOiIxOTg5MDUyMTgwNzIifQ==",
"minRegistrationLevel":"PLUS","title":"Sign transaction","expiry":1517526000000,"dataToSignType":"SIMPLE_UTF8_TEXT",
"dataToSign":{"text":"VGhpcyBpcyBhIHRleHQgZm9yIHNpZ24gdHJhbnNhY3Rpb24u"},"signatureType":"SIMPLE"}Encode the JSON structure to Base64.
Create the HTTP POST request with a POST parameter name initSignRequest and the Base64 encoded JSON structure from the step 4 as its value.
The HTTP body should be the following (compact format, line broken for clarity only):
initSignRequest=eyJ1c2VySW5mb1R5cGUiOiJTU04iLCJ1c2VySW5mbyI6ImV5SmpiM1Z1ZEhKNU
lqb2lVMFVpTENKemMyNGlPaUl4T1RnNU1EVXlNVGd3TnpJaWZRPT0iLCJtaW5SZWdpc3RyYXRpb25M
ZXZlbCI6IlBMVVMiLCJ0aXRsZSI6IlNpZ24gdHJhbnNhY3Rpb24iLCJleHBpcnkiOjE1MTc1MjYwMD
AwMDAsImRhdGFUb1NpZ25UeXBlIjoiU0lNUExFX1VURjhfVEVYVCIsImRhdGFUb1NpZ24iOnsidGV4
dCI6IlZHaHBjeUJwY3lCaElIUmxlSFFnWm05eUlITnBaMjRnZEhKaGJuTmhZM1JwYjI0dSJ9LCJzaW
duYXR1cmVUeXBlIjoiU0lNUExFIn0=UPI userInfoType Example Request
If you wish to initiate a sign request for a user with unique personal identifier '5633-823597-7862':
Create the JSON structure: {"userInfoType":"UPI","userInfo":"5633-823597-7862","minRegistrationLevel":"BASIC","title":"Sign transaction","confidential":false,"expiry":1517526000000,"dataToSignType":"SIMPLE_UTF8_TEXT","dataToSign":{"text":"VGhpcyBpcyBhIHRleHQgZm9yIHNpZ24gdHJhbnNhY3Rpb24u"},"signatureType":"SIMPLE"}.
Encode the JSON structure to Base64.
Create the HTTP POST request with a POST parameter name initSignRequest and the Base64 encoded JSON structure from the step 2 as its value.
The HTTP body should be the following (compact format, line broken for clarity only):
initSignRequest=eyJ1c2VySW5mb1R5cGUiOiJVUEkiLCJ1c2VySW5mbyI6IjU2MzMtODIzNTk3LTc4NjIiLCJtaW5SZWdp
c3RyYXRpb25MZXZlbCI6IkJBU0lDIiwidGl0bGUiOiJTaWduIHRyYW5zYWN0aW9uIiwiY29uZmlkZW50aWFsIjpmYWxzZSwi
ZXhwaXJ5IjoxNTE3NTI2MDAwMDAwLCJkYXRhVG9TaWduVHlwZSI6IlNJTVBMRV9VVEY4X1RFWFQiLCJkYXRhVG9TaWduIjp7
InRleHQiOiJWR2hwY3lCcGN5QmhJSFJsZUhRZ1ptOXlJSE5wWjI0Z2RISmhibk5oWTNScGIyNHUifSwic2lnbmF0dXJlVHlw
ZSI6IlNJTVBMRSJ9Possible Errors
Code Returned | Explanation |
|---|---|
0 | Internal error. |
1001 | Invalid or missing userInfoType. |
1002 | Invalid or missing userInfo. |
1003 | Invalid restrict. |
1004 | You are not allowed to call this method. |
1005 | User has disabled your service. |
1006 | Invalid confidential. |
1007 | Invalid min registration level. |
1008 | Unknown Relying Party. |
1009 | You are not allowed to request integratorSpecificUserId parameter. |
1010 | JSON request cannot be parsed. |
1012 | User with the specified userInfo does not exist in Freja eID database. |
3000 | Invalid or missing dataToSignType. |
3001 | Invalid or missing dataToSign. |
3002 | Invalid or missing signatureType. |
3003 | Invalid expiry time. |
3004 | Invalid push notification. |
3005 | Invalid attributesToReturn parameter. |
3006 | Custom identifier has to exist when it is requested. |
3007 | Invalid title. |
3008 | Invalid SSN for advanced signing. Advanced signing cannot be performed by users from your country. |
3009 | Invalid advanced signing request. Missing SSN and basicUserInfo in its attributesToReturn parameters. |
JSON Response Value
If HTTP 200 is returned from the method, the following return value will be present in the body of the response:
{
"signRef":"Reference to be submitted in getOneResult method"
} |
|
JSON Response Value if useDynamicQrCode is set to TRUE
{
"signRef":"Reference to be submitted in getOneResult method",
"qrCodeSecret":"Secret used for generating dynamic QR code"
} |
|
Get One Signature Result Method
The method is called using HTTP POST through the URLs below:
Environment | Endpoint |
|---|---|
TEST |
|
PRODUCTION |
|
JSON Example for getOneSignResultRequest
The parameter of the method is a Base64 UTF8-encoded JSON payload according to the following:
{
"signRef":"Signature reference"
} | signRef: string, mandatory. The value must be equal to a signature reference previously returned from a call to the Initiate Sign Method. The time period during which a specific signature reference is available for checking will depend on the longevity of the signature operation see the expiry parameter in the Initiate Sign method) and is calculated as expiry time plus 3 days. |
Example Request
If you wish to fetch a single signature result with the signature reference previously returned from a call to initSignRequest (for a user with an email address joe.black@freja.com), follow these steps:
Create the JSON structure {"signRef":"TrLA9zdxCBlNOQNvkdhAM14mJmlL20digC7+QgEVRwmE7SH8Qm0swWIc6whfKm4Y"}
Encode the JSON structure to Base64.
Create the HTTP POST request with a POST parameter name getOneSignResultRequest and the Base64 encoded JSON structure from the step 2 as its value.
The HTTP body should be the following:
|
Possible Errors
Code Returned | Explanation |
|---|---|
1004 | You are not allowed to call this method. |
1008 | Unknown Relying Party. |
1100 | Invalid reference (for example, nonexistent or expired). |
JSON Response Value
If HTTP 200 is returned from the method, the following return value will be present in the body of the response:
{
"signRef":"Signature reference",
"status":"Signature status",
"details":"JWS signed data",
"requestedAttributes":"Additional attributes about the user"
} |
|
details
The content of this response element will depend on the signatureType requested when the signature was initiated.
Simple Signature Type
JWS in compact serialised form as following:
BASE64URL(UTF8(JWS Protected Header)) || ’.’ || BASE64URL(JWS Payload) || ’.’ || BASE64URL(JWS Signature)
JWS Protected Header | |
{
"x5t":"SHA-1 digest of the signing certificate",
"alg":"algorithm used to secure the JWS"
} |
|
JWS Payload | |
{
"signRef":"Signature reference",
"status":"Signature status",
"userInfoType":"User info type",
"userInfo":"User information corresponding to user info type",
"minRegistrationLevel":"Minimum required registration level of a user",
"timestamp":"Time when signature was confirmed by end user",
"signatureType":"Signature type",
"signatureData": {
"userSignature":"The signature produced by the end user",
"certificateStatus":"Evidence of end-users certificate status",
"advancedSignature" : "If requested, the advanced signature"
},
"requestedAttributes":{
"JSON object"
},
} |
|
Advanced Signature Type
The XML_MINAMEDDELANDEN format generates XML signatures as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#”>
<SignedInfo>
<CanonicalizationMethod> Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/
<SignatureMethod> Algorithm="https://www.w3.org/2001/04/xmldsig-more#rsa-sha256%22"/
<Reference> URI="#object">
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256”>
<DigestValue>JmvMxPgYwsd3oHadDF3v8cJQdN5qkBR7cCF3ap/ZAKI=
</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>ZZIkJR1I7imz2AG0+hsWFtmI/4JMxwAvozqkcKbEs3kAIR+KD5kDqnqsit1nULxk9sFfoFv6i4+l >
9eAfegBCh4Jlcex+ZR2pjrPqNx0SPrtg+MtvLV9ruICbj0u/RO2nOhzJtcTBoTtHRfJxV/Ji0Lyw
KmtAK6h/zEcIJujwSwqYZ37hX5KqmWxgtcgc00Loiaq8IxrJuyBQhUoWvH7jgqlwWHy5To+aMOlk
XdGE7fa4HRvNxJolLMPevC54r/NR5X1x7LmMqiDeZYn4KB8Q+twM5jGS6C/5kGZBIzB5pf1ovkZ6
0F2TuCklAegyfV/ksBIL9l6DN5ZJVJF0PFVmxA==</SignatureValue>
<KeyInfo Id="frejaKeyInfo">
<X509Data>
<X509Certificate>base 64 end-entity certificate</X509Certificate>
<X509Certificate>base 64 CA certificate</X509Certificate>
</X509Data>
</KeyInfo>
<Object Id="object">
<frejaSignedData id="frejaSignedData">
<userData>
<usrVisibleData>base64 encoded text that was displayed to the user</usrVisibleData>
<userDeviceSignature>json signature produced on the mobile phone</userDeviceSignature>
</userData>
<additionalData>
<signingTime>1666355503547</signingTime>
</additionalData>
</frejaSignedData>
</Object>
</Signature>Get Signature Results Method
The method is called using HTTP POST through the URLs below:
Environment |
|---|