# DEPRECATED DOCUMENT - DON'T USE!!
updated information is available here: https://hackmd.io/-19y7o9aQZuWL113KZOB6w?view
### Tasks
- [x] complete basic messages in [Data Models](#Data-Models)
- [x] describe [SMS Registration](#SMS-Registration) Plugin
- [x] CFA: describe [ID Austria](#ID-Austria-Registration) Plugin
- [x] setup most simple dev environment
- [x] demonstrate [simple onboarding](#MVD-Minimum-Viable-Demonstration)
## Onboarding Sequence & Roles
```plantuml
@startuml
actor Client as client
participant "REGAPI v2\n(root)" as root
participant "RegAPI v3" as api
queue Redis as redis
collections "Plugins\nsms,ida" as worker
collections "Identity\nProvider" as id
database "Persistent\nStorage" as storage
autonumber
worker -> redis: subscribe individual method
client -> root: **GET /config/root**
client <-- root: root configuration
client -> api: **PUT /register**
api -> redis: create reg_id &\npublish &\nestablish object
client <-- api: registration\n(reg_id)
redis --> worker: registration request
group Individual Identity Provider
worker -> id: trigger request
note left worker: internal sequence passing\ninformation between Client\nand Plugin communication\nvia get/set object
worker <-- id: verified identity
end
worker -> redis: update Redis object
client -> api: **GET /register(reg_id)**
api -> redis: query Redis objects\nbased on reg_id
api <-- redis: Redis response
note right api: in case there is no object on Redis with\nthe given reg_id, information might be\navailable in the persistent storage
api -> storage: check if already registered
api <-- storage: credentials / FALSE
note right api: in case there are credentials from the\npersistent sotrage -> cache the information\non Redis
api -> api: persist credentials\nwith reg_id
client <-- api: registration(state, data)
```
#### Sequence Notes
1) Worker: subsribe respective method
redis-cli: `subscribe sms`
redis-cli: `subscribe ida`
2) Client: **GET /config/root**
3) *GET Response:* [root configuration](#Root-Configuration)
4) **PUT /register** [Request body](#Registration)
5) RegAPI:
* check availability of channelname = method
redis-cli: `PUBSUB CHANNELS`
* includes method?
* create unique reg_id (if not provided in request)
* establish Redis object
[Redis object](#Redis-Object)
* (6) respond with reg_id
* (7) publish request to channel
6) *PUT Response:* reg_id for subsequent queries
`{"reg_id":"string"}`
7) publish request to channel = method
redis-cli: `pub ida "{Redis message}"`
[Redis message](#Redis)
8) communication to identity mechanism - see [available Plugins](#Plugins)
9) communcation from identity mechanism - see [available Plugins](#Plugins)
10) update [Redis object](#Redis-Object)
11) **GET /register/{reg_id}** periodical requests from the client
12) query Redis for object with `reg_id`
13) query response: [Redis object](#Redis-Object)
14) in case the query above resulted in no response the fall back is to query the persistent storage
request to [PostgreSQL](#PostgreSQL-Query)
request to [Kamailio](#Kamailio-Query)
15) response from persistent storage
16) in case the persistent storage provided information for a `reg_id` that is currently not available on Redis --> a new Redis object should be created with the redentials for this `reg_id`
17) *Response:* [Registration state](#Registration-state)
#### Open Quesionts
* single Redis Channel that all Registration Plugins listen to vs. individual channels per method --> decision: multiple channels
* ~~single channel: easy communication during onboarding~~
* multiple channels: easy identification if plugin is available (and functional)
## Scenarios
The following scenarios are considered (and should be tested) for the RegAPI:
* creating a new account via SMS registration
* creating a new account via ID Austria registration
* resetting an ongoing registration flow
* recovering from crash scenarios
* RegAPI v3 not available
* Redis not available
* SMS Plugin not available
* ID Austria not available
* PostgreSQL (persistent storage) not available
* Kamailio not available
### Resetting an Ongoing Registration Flow
The client can initiate at any time that a registration flow should be cancled by sending a reset message with **PUT /register** and this [Body](#Request-Body-for-resetting-a-Registration)
The RegAPI should then trigger to remove any Redis object with this `reg_id`
## List of Statuses
| Code | Text | Description |
| ---- | ---- | ----------- |
|<tr><td colspan="3">set by RegAPI (range: 1001-1099)</td></tr>|
| 1001 | `initial` | initial state with action `init` |
| 1002 | `{method} plugin triggered` | triggered plugin (usually specified in 'method') |
| 1003 | `{action} received, {method} plugin triggered` | triggered plugin specified in 'method' in 'action' |
| 1004 | `REG_ID removed` | after successful deletion of `:reg_id`in Redis |
|<tr><td colspan="3">set by SMS Plugin (range: 1100-1199)</td></tr>|
| 1100 | `SMS verification passed` | SMS verification successfully performed |
| 1101 | `SMS Plugin: SMS sent` | successfully sent SMS code |
| 1102 | `SMS Plugin: Email sent` | successfully sent code via Email (only in EMAIL_TEST_MODE) |
| 1103 | `SMS Plugin: cannot send SMS code` | error on sending SMS code |
| 1104 | `SMS Plugin: invalid input for 'SmsVerificationCode'` | payload provided by client cannot be parsed |
| 1105 | `SMS Plugin: invalid input in 'SmsVerificationCode'` | payload provided by client does not include 'sms_code' |
| 1106 | `SMS Plugin: invalid SMS code provided` | sms_code provided by client does not match code sent out |
| 1107 | `SMS Plugin: internal error in SMS code handling` | error on encrypting/decrypting SMS code |
| 1108 | `SMS Plugin: invalid phone number` | provided phone number does not match format provided in "PHONE_NUMBER_VERIFICATION" |
| 1109 | `SMS Plugin: SMS resend limit ({max}) reached` | too many requests for re-sending SMS |
|<tr><td colspan="3">set by ID-Austria Plugin (range: 1200-1299)</td></tr>|
| 1200 | `ID_AUSTRIA verification passed` | verification through ID Austria successfully performed |
| 1201 | `ID Austria URL generated` | URL for user to authenticate with ID Austria |
| 1202 | `ID Austria Plugin: invalid action` | unknown request |
| 1203 | `ID_AUSTRIA Plugin: invalid response` | error in processing the response A-Trust |
|<tr><td colspan="3">set by ID-Austria Plugin (range: 1000, 9001-9099)</td></tr>|
| 1000 | `SIP credentials created` | SIP plugin successfully created and onboarding completed |
| 9001 | `SIP Plugin: error on creating SIP credentials` | error in SIP Plugin |
| 9002 | `SIP Plugin: missing configuration 'SIP_SECRET'` | SIP_SECRET not configured (to be used with token for deleting users) |
| 9003 | `SIP Plugin: error on connecting to Kamailio DB` | connection information to Kamailio is not valid |
| 9004 | `SIP Plugin: error on writing subscriber table` | error in SQL INSERT command |
## Plugins
### SMS Registration
#### Sequence Diagram for SMS Registration
```plantuml
@startuml
actor "Client" as client
participant "RegAPI v3" as api
queue "Redis" as redis
participant "SMS Plugin" as plugin
participant "Firmen SMS" as firmensms
plugin -> redis: subscribe "sms" channel
== SMS Verification ==
redis -> plugin: registration request
plugin -> plugin: create phone\nverification code
plugin -> firmensms: trigger sending verification code\nto provided phone number
plugin -> redis: update Redis object with reg_id\nto new state "SMS sent"
group optional
client -> api: **GET /registration/{reg_id}**
api -> redis: query reg_id
api <-- redis: new state
client <-- api: state "SMS sent"
end group
client <- client: receive SMS code\nfrom Firmen SMS
client -> api: **PUT /register**
api -> redis: publish reg_id object\nwith SMS code entered\nby client
redis -> plugin: Redis reg_id object update\n(from subscription)
plugin -> plugin: verify provided code
plugin -> redis: update Redis object with reg_id\nto new state "SMS verified" or\nnew state "SMS verification falied"
== Create Credentials ==
client -> api: periodic\n**GET /registration/{reg_id}**
api -> redis: query reg_id
api <-- redis: new state
api -> api: perform steps to register\ncredentials on PostgreSQL\n& Kamailio
```
**Input**
* phone number
**Output**
* confirmation of phone number
### ID Austria Registration
**Notes**
* requires Client interaction in the process
#### Sequence Diagram for SMS Registration
```plantuml
@startuml
actor "Client" as client
participant "A" as a
participant "B" as b
a -> b: text
```
### Account Setup in Kamailio
### Write to PostgreSQL
## Data Models
### Root Configuration
`GET /config/root`
Response Body:
```json=
{
"root": {
"country registries": [{
"name": "AT",
"registration_api": {
"type": "dec112_v1",
"url": "https://service.dec112.at"
}
}]
},
"runtime ms": "0.49305"
}
```
### Registration
`PUT /register`
<details><summary>Attributes</summary>
* phone number (depends)
- based on purpose
- mandatory for chat, silent
- otherwise optional
- can't access phone number from within app
- used as display name for SIP configuration
* model (optional)
* lang (mandatory)
- to be set by app
* method (optional, default: "sms")
- based on device (app, web)
- possible values
- sms: SMS registration
- ida: registration via ID Austria
- email: Email
* purpose (optional, default: "chat")
- chat: register DEC112 chat
- silent: register silent emergency notification
- sensor: register IoT sensor
* application
- DEC112 app -> possibly with version nr
- web
- wallet
- iot
</details>
**List of Actions:**
* init
* SmsVerificationCode
* delete
Request Body - initial:
```json=
{
"header": {
"reg_id":null
"method":"sms",
"action":"init"
},
"payload":{
"phone_number":"string",
"model":"string",
"lang":"de",
"purpose":"chat",
"applicaiton":"string"
}
}
```
Request Body for SMS Registration:
```json=
{
"header": {
"reg_id":"string",
"method":"sms",
"action":"SmsVerificationCode"
},
"payload":"{\"code\":\"123456\"}"
}
}
```
##### Request Body for resetting a Registration:
```json=
{
"header": {
"reg_id":"string",
"method":"string",
"action":"delete"
}
}
```
### Redis
#### Redis Storage (options)
There are 3 options to store JSON:
1. String (just store pre-serialized data as native Redis key => `reg_id`). _Note: there is no direct way to manipulate values_
```bash=
127.0.0.1:6379> SET cb29028e-f459-3844-01bc-fb2d38af3c93 '{ "reg_id":"string", "phone_number":"string", "model":"string", "lang":"de", "method":"sms", "purpose":"chat", "application":"string" }'
OK
```
```bash=
127.0.0.1:6379> GET cb29028e-f459-3844-01bc-fb2d38af3c93
"{ \"reg_id\":\"string\", \"phone_number\":\"string\", \"model\":\"string\", \"lang\":\"de\", \"method\":\"sms\", \"purpose\":\"chat\", \"application\":\"string\" }"
```
2. Hashes (map string field and string values and store it in a hash => `reg_id`). _Note: values can be manipulated_
```bash=
127.0.0.1:6379> HMSET cb29028e-f459-3844-01bc-fb2d38af3c93 reg_id "string" phone_number "string" model "string" lang "de" method "sms" purpose "chat" application "string"
OK
```
```bash=
127.0.0.1:6379> HGETALL cb29028e-f459-3844-01bc-fb2d38af3c93
1) "reg_id"
2) "string"
3) "phone_number"
4) "string"
5) "model"
6) "string"
7) "lang"
8) "de"
9) "method"
10) "sms"
11) "purpose"
12) "chat"
13) "application"
14) "string"
15) "state"
```
```bash=
127.0.0.1:6379> HGET cb29028e-f459-3844-01bc-fb2d38af3c93 method
"sms"
```
3. JSON support for Redis. _Note: requires Redis JSON module, see https://redis.io/docs/data-types/json/_
:::danger
:warning: we need a single method/command. WK: I'd suggest Redis Hashes ...
:::
#### Redis Hashes
Data objects (per registration) are stored as Redis hashes (see example below).
```bash=
127.0.0.1:6379> HMSET cb29028e-f459-3844-01bc-fb2d38af3c93 reg_id "string" phone_number "00436641234567" model "string" lang "de" method "sms" purpose "chat" application "string"
OK
```
Hashes are used as 'message' part in PUB/SUB transactions, to trigger other services (see example below to trigger an sms service).
```bash=
127.0.0.1:6379> PUBLISH sms cb29028e-f459-3844-01bc-fb2d38af3c93
(integer) 0
```
Generic format: `PUBLISH {method} {reg_id}`
Services subscribed to this channel may access data using `HGET`, e.g. sms service may query the phone number:
```bash=
127.0.0.1:6379> HGET cb29028e-f459-3844-01bc-fb2d38af3c93 phone_number
"00436641234567"
```
:::danger
:warning: Lets discuss this idea, perhaps there is another way to combine PUB/SUB and Redis caching mechanims.
:::
#### ~~Redis Object~~
JSON:
```json=
{
"reg_id":"string"
"phone_number":"string",
"model":"string",
"lang":"de",
"method":"sms",
"purpose":"chat",
"applicaiton":"string"
}
```
### Registration state
JSON:
```json=
{
"header": {
"reg_id":"string",
"state":integer
},
"payload" : {
...
}
}
```
#### States in Registration Flow
* `1` init
* `10` finished
### Subscriber Management
#### Requirements for SIP Plugin
* subscribe to Redis channel `sip`
* on new request on `sip` create random strings for username & password
* create entry in [Kamailio Subscriber Table](#Kamailio-Subscriber-Table)
* encrypt username and password and write to Redis Hashmap Storage
* `public_key` is available on Redis Hashmap Storage for current request
example: key representation uses [MultiFormat](https://multiformats.io/)
* `public_key: z6Lc3rZVvBcjJ5Atb2smre9egeaYWqpo1oKCrC3Z5N8DcTXD`
encoding: [multibase](https://github.com/multiformats/multibase) (base58btc), [multicodec](https://github.com/multiformats/multicodec/blob/master/table.csv) (x25519-pub)
* `private_key: z1S5gX4Fqq2GjLzfPkJhVdRsaT7uerAqYn3HxQCAk9Qa8mm4`
(just for completeness -> will not be available to SIP plugin)
* encoding: multibase (base58btc), multicodec (ed25519-priv)
* encrypted string `hello world` with public key from above using [libsodium autenticated encryption, combined mode](https://libsodium.gitbook.io/doc/public-key_cryptography/authenticated_encryption#combined-mode):
`{"value"=>"dcfdc7004080371adab46e8fba25aaa4efc3553bcfffdb12941eb3", "nonce"=>"2ce4cd81b61e807fb1ba8c88ce4271a3b48097f52918154b"} `
* publish reg_id on channel `state_change`
#### PostgreSQL Identity Table
:::danger
:warning: from discussion Mon Sept 4 between Wolfgang & Christoph: Identity Table might not be necessary
:::
:::warning
:warning: incomplete ... requires further discussion
:::
| name | type | size | default | null | key | extra attributes | description |
| ---- |----- | ---- | ------- | ---- | --- | ---------------- | ----------- |
| id | unsigned int | 10 | | no | primary | autoincrement | Unique ID |
| reg_id | string | 36 | '' | no | | | GUID |
| sipuser | string | 64 | '' | no | | | Username |
| ... |
##### Table Values
* reg_id => `GUID(...)`
* ...
##### PostgreSQL Query
* insert values and check if `reg_id` exists (on fail: create new values)
```bash
INSERT INTO
identity(reg_id, ...)
VALUES
(reg_id, ...)
ON CONFLICT
(reg_id)
DO NOTHING;
```
* read values
```bash
SELECT
reg_id,
username,
...
FROM
identity
WHERE
reg_id = 'cb29028e-f459-3844-01bc-fb2d38af3c93';
```
* delete values
```bash
DELETE
FROM
identity
WHERE
reg_id = 'cb29028e-f459-3844-01bc-fb2d38af3c93';
```
#### Kamailio Subscriber Table
* for more information see https://kamailio.org/docs/db-tables/kamailio-db-5.5.x.html#gen-db-subscriber
| name | type | size | default | null | key | extra attributes | description |
| ---- |----- | ---- | ------- | ---- | --- | ---------------- | ----------- |
| id | unsigned int | 10 | | no | primary | autoincrement | Unique ID |
| username | string | 64 | '' | no | | | Username / phone number |
| domain | string | 64 | '' | no | | | Domain name (realm) |
| password | string | 64 | '' | no | | | Password |
| ha1 | string | 128 | '' | no | | | md5(username:realm:password) |
| ha1b | string | 128 | '' | no | | | md5(username@domain:realm:password) |
##### Table Values
:::info
:warning: the following requires `reg_id` as input
:::
* username => `MD5(reg_id + ':' + random string[26])`
* domain => "service.dec112.at"
* password => `MD5(random string[26])`
* ha1 => `MD5(username + ':' + domain + ':' + password)`
* ha1b => `MD5(username@domain + ':' + domain + ':' + password)`
proposal:
* username => `sha256(random string[26])`
:::danger
:warning: we need a separate table to map `reg_id` to `username`; see [Identity Table](#PostgreSQL-Identity-Table)
:::
##### Kamailio Query
* insert values and check if username exists (on fail: create new values)
```bash
INSERT INTO
subscriber(username, domain, password, ha1, ha1b)
VALUES
(username, domain, password, ha1, ha1b)
ON CONFLICT
(username)
DO NOTHING;
```
* insert username into [Identity Table](#PostgreSQL-Identity-Table)
```bash
INSERT INTO
identity(sipuser)
VALUES
(username)
WHERE
reg_id = 'cb29028e-f459-3844-01bc-fb2d38af3c93';
```
* read values
```bash
SELECT
username,
domain,
password
FROM
subscriber
WHERE
username = 'ec7c15fd7f2199a58e8fd28b186d180b';
```
* delete values
```bash
DELETE
FROM
subscriber
WHERE
username = 'ec7c15fd7f2199a58e8fd28b186d180b';
```
#### Sequence Diagram to create credentials
```plantuml
@startuml
actor "Client" as client
participant "RegAPI v3" as api
queue "Redis" as redis
database "PostgreSQL" as psql
database "Kamailio" as proxy
== Create Credentials ==
client -> api: **PUT /register**
api -> redis: query reg_id
api <-- redis: unknown
api -> api: create unique reg_id\n(GUID)
api -[#red]> psql: INSERT INTO\n\tidentity(reg_id, ...)\nVALUES\n\t(**reg_id**, ...)
api -> redis: publish reg_id object
api -> client: registration(reg_id, state=1)
client -> api: periodic\n**GET /registration/{reg_id}**
api -> client: registration(reg_id, state=1)
note right of api: verification via sms ... successful
api -> api: create user,\npw, ha1, ha1b
api -[#red]> proxy: INSERT INTO\n\tsubscriber(username, domain, password, ...)\nVALUES\n\t(username, domain, password, ...)
api -[#red]> psql: INSERT INTO\n\tidentity(sipuser, ...)\nVALUES\n\t(username, ...)\nWHERE reg_id == '**reg_id**'
api -> redis: publish reg_id object\nwith user, pw, domain,\nha1, ha1b
== Retrieve Credentials ==
client -> api: periodic\n**GET /registration/{reg_id}**
api -> redis: query reg_id
api <-- redis: sip credentials
api -> client: registration(reg_id, state=10)
```
### Registration Response `state=1`
JSON:
```json=
{
"reg_id": "cb29028e-f459-3844-01bc-fb2d38af3c93",
"state": 1,
...
}
```
### Registration Response `state=10`
JSON:
```json=
{
"reg_id": "cb29028e-f459-3844-01bc-fb2d38af3c93",
"state": 10,
"server": "ws://service.dec112.at",
"public_id": "sip:ec7c15fd7f2199a58e8fd28b186d180b@service,dec112.at",
"private_id": "ec7c15fd7f2199a58e8fd28b186d180b",
"password": "6679793d96ec618e453803b4d1b0485b",
"realm": "service.dec112.at",
...
}
```
#### C code to generate MD5 digest `ha1` (openssl)
```bash=
// file.c
// compile with: gcc -o md file.c -lcrypto
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
int main(int argc, char *argv[]) {
EVP_MD_CTX *mdctx;
const EVP_MD *md;
const char mdname[] = "MD5"; // or "SHA256"
const char user[] = "user";
const char realm[] = "service.dec112.at";
const char pw[] = "secret123";
unsigned char md_value[EVP_MAX_MD_SIZE];
int md_len, i;
md = EVP_get_digestbyname(mdname);
if (md == NULL) {
printf("unknown message digest %s\n", mdname);
exit(1);
}
mdctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, user, strlen(user));
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, realm, strlen(realm));
EVP_DigestUpdate(mdctx, ":", 1);
EVP_DigestUpdate(mdctx, pw, strlen(pw));
EVP_DigestFinal_ex(mdctx, md_value, &md_len);
EVP_MD_CTX_free(mdctx);
printf("%s[%d]: ", mdname, md_len);
for(i = 0; i < md_len; i++) {
printf("%02x", md_value[i]);
}
printf("\n");
return 0;
}
/*
$ ./md
MD5[16]: 8874508e1ca0b1158b30cb95b65b8b5f
$ ./md
SHA256[32]: c5c24d18d6e0da6608fc0afdcf763eb2398d0f06ab2ea21f8a421400650a06fa
*/
```
#### C code to generate GUID (simplest option :smile:)
```bash=
// file.c
// compile with: gcc -o guid file.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
void gen_uuid(char **buf, size_t len) {
char v[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char *tmp = *buf;
time_t t;
if ((*buf == NULL) || (len != 36)) {
tmp = NULL;
return;
}
srand((unsigned)time(&t));
for (int i = 0; i < len; ++i) {
*(tmp + i) = v[rand() % 16];
}
*(tmp + 8) = '-';
*(tmp + 13) = '-';
*(tmp + 18) = '-';
*(tmp + 23) = '-';
*(tmp + len) = '\0';
return;
}
int main(int argc, char *argv[]) {
char uuid[36];
char *guid = &uuid[0];
gen_uuid(&guid, 36);
printf("GUID[%d]: %s\n", (int)strlen(uuid), uuid);
return 0;
}
/*
$ ./guid
GUID[36]: cb29028e-f459-3844-01bc-fb2d38af3c93
*/
```
## Example Data Flows
### MVD (Minimum Viable Demonstration)
Components:
* RegAPI v3
* Redis
* Worker
* simulated identity provider
## Redis Notes
local instance of Redis:
```bash
docker run --name redis -d -p 6379:6379 redis
```
access with `redis-cli` ([package redis-tools](https://packages.debian.org/buster/redis-tools))
```bash
redis-cli -h 127.0.0.1 -p 6379
> set reg_id '{"key":"value"}'
> get reg_id
> pub "sms" '{"key":"value"}'
> sub "sms"
```
## Security Notes
We need some kind of DDoS protection:
* Any IP must not try to register a new device more than X times per X hours
* A phone number must not be used multiple times in a row for verification
* Device Integrity:
* https://developer.android.com/google/play/integrity/overview
* https://developer.apple.com/documentation/devicecheck/establishing_your_app_s_integrity
## Diagrams
### Architecture Overview
```plantuml
@startuml "overview"
skinparam handwritten true
skinparam RectangleBackgroundColor white
skinparam NoteBackgroundColor APPLICATION
skinparam NoteBorderColor black
skinparam actorStyle Hollow
rectangle "Mobile Wallet" {
rectangle "SSI Wallet" as wallet #lightgreen
}
rectangle "Application" {
rectangle "DEC112 App" as decapp
}
rectangle "Registration" {
rectangle "DEC112 RegAPI" as regapi #lightgreen
}
rectangle "SIP Service" {
rectangle "DEC112 SIP Proxy" as proxy
database "PSQL" as db
}
rectangle "NG Core Services" {
rectangle "Security Service" {
rectangle "BCF" as bcf
}
rectangle "Routing Service" {
rectangle "ESRP" as esrp
}
rectangle "Mapping Service" {
rectangle "ECRF" as ecrf
}
}
rectangle "ECC Service" {
rectangle "DEC112 Viewer" as border
rectangle "DEC112 Chatbot" as bot #lightgreen
}
rectangle "ID Austria" as ida
wallet <-> :User:
:User: <-> decapp
regapi .[#black]>> db
proxy <<.[#black]>> db
decapp .left[#black]>> regapi
decapp -[#black]-> proxy
wallet -[#black]-> proxy
ida .up[#black]->> wallet
ida .left[#black]->> regapi
proxy -[#black]-> bcf
bcf -[#black]-> esrp
esrp <.[#black]-> ecrf
esrp -[#black]-> border
esrp -[#black]-> bot
border <-> :Call Taker:
@enduml
```
### Registration API
```plantuml
@startuml "architecture"
skinparam handwritten true
skinparam RectangleBackgroundColor white
skinparam NoteBackgroundColor APPLICATION
skinparam NoteBorderColor black
skinparam BackgroundColor transparent
skinparam componentStyle rectangle
rectangle "DEC112" {
component "DEC112 App" as app
rectangle "SIP Proxy" as proxy
database "PSQL" as db
proxy .[#black]-> db
}
component "ID Provider" {
component "ID Austria" as id {
}
}
component "SMS Provider" {
component "SMS" as smsc {
}
}
rectangle RegAPI {
rectangle "SMS Service" {
component "sms" as sms {
}
}
rectangle "SIP Service" {
component "sip" as kamailio {
}
}
rectangle "ID Service" {
component "id" as identity {
}
}
rectangle "REST Endpoint" {
component "api" as rest #DarkGray {
}
}
component "REDIS" as redis1 #LightBlue {
component "storage" as storage {
}
}
component "REDIS" as redis2 #LightBlue {
component "pub/sub" as pubsub{
}
}
rectangle "... Service" {
component "..." as any {
}
}
}
app <-[#black]-> rest
kamailio --[#black]-> redis1
kamailio --[#black]-> redis2
kamailio .[#black]-> db
sms --[#black]-> redis1
sms --[#black]-> redis2
sms .[#black]-> smsc
smsc .[#black]-> app
identity --[#black]-> redis1
identity --[#black]-> redis2
identity .[#black]-> id
any --[#black]-> redis1
any --[#black]-> redis2
rest --[#black]-> redis1
rest --[#black]-> redis2
@enduml
```
### SMS Flow
```plantuml
@startuml
hide empty description
[*] --> app_init
state "App" as app_init
app_init: create / use DID\nPUT /register
app_init -right-> regapi_start
state "RegAPI" as regapi_start
regapi_start: check/create Redis Store object\npub SMS\n\nstate: "init"
regapi_start -right-> sms_code
state "SMS Plugin" as sms_code
sms_code: send SMS code\n\n\nstate: "SMS sent"
sms_code -down-> ph1
state " " as ph1
ph1 -left-> app_code
state "App" as app_code
app_code: enter code\nPUT /register
app_code -right-> regapi_sms
state "RegAPI" as regapi_sms
regapi_sms: pub SMS\n\n\n\nstate: "code received"
regapi_sms -right-> sms_verify
state "SMS Plugin" as sms_verify
sms_verify: verify code\nupdate Redis Store\npub StateChange\n\nstate: "code verified"
sms_verify -right-> regapi_sip
state "RegAPI" as regapi_sip
regapi_sip: sub StateChange or GET /register/DID\npub Kamailio\n\n\nstate: "create SIP credential"
regapi_sip -right-> kamailio
state "Kamailio Plugin" as kamailio
kamailio:create SIP credentials\nencrypt credentials with PubKey from DID\nupdate Redis Store\n\nstate: "SIP credential created"
kamailio -down-> ph2
state " " as ph2
ph2 -left-> app_query
state "App" as app_query
app_query: GET /register/DID
app_query -right-> regapi_finish
state "RegAPI" as regapi_finish
regapi_finish: respond with encrypted SIP credentials in Redis Store\n\nstate: "finished"
regapi_finish --> app_finish
state "App" as app_finish
app_finish: decrypt and store SIP credentials
app_finish --> [*]
@enduml
```
### Sequence Diagram ID Austria
HackMD: https://hackmd.io/YY15ymg7QBKxv-BOQAieWQ#DEC112-Onboarding-with-ID-Austria