Skip to content

Latest commit

 

History

History
333 lines (236 loc) · 10.6 KB

operator-design-alternative-swan.md

File metadata and controls

333 lines (236 loc) · 10.6 KB

SWAN

Although not implementing the same Operator Design, [SWAN](swan/apis.md at main · SWAN-community/swan · GitHub) provides a solution that can be used for all workflows.

Some core principles of SWAN are:

  • all data is encrypted and decrypted by the operator (using its private key) before to be sent over the network

  • clients need to do a server to server call to the access node before each communication

    • the client is authenticated via its "API key" during this preliminary handshake
  • the "access node" is a particular node in the operator network, responsible for handling encryption and decryption for clients

  • messages are using a proprietary binary format for transport and cookie storage, for optimization

  • it is originally made to support a tree of operator nodes, under a different domain, although the solution works with a single TLD+1 domain.

The SWAN solution is very modular, based on different open source projects (OWID, SWIFT) and meant to be generic (not limited to the Prebid Addressability Framework use case).

✅ the level of security is high because all data is encrypted

✅ robust solution with existing implementations and demo

Limitations:

🟠 to support a wide variety of use cases, it has a complicated code and workflow and unnecessary S2S calls and redirects

  • calls to encrypt and decrypt are systematic, even when encryption is unactivated

  • scrambling of cookie paths

  • the whole system is meant to support multiple nodes (notion of home node, handling of data collision, etc) which makes it overcomplicated for the single node use case

🟠 mandatory backend client

🟠 obscure to web users and regulators

🟠 complex integration and debug

ℹ️ the diagram below is based on the SWAN demo, where CMP is considered to be a dedicated web site that the user is redirected to, not an integrated widget. This counts for a few extra redirects that could probably be avoided.

sequenceDiagram
participant U as user
participant B as browser
participant P as publisher P http server
participant C as CMP http server
participant A as advertiser A http server
participant O as operator node O
participant AN as aperator access node AO

rect rgba(224, 224, 224, .55)
note right of U: Time T1<br>"WRITE" scenario: user visits publisher<br>and sets their preferences for the first time

    U ->> B: visit www.publisherP.com/pageP.html
    activate U

        activate B
            B ->> P: GET /pageP.html
        deactivate B

        activate P
            P ->> P: no Prebid SSO ID 🍪 found
            P ->> AN: (S2S) POST /fetch<br>APIkey=keyP<br>redirectUrl=publisherP.com/pageP.html

          activate AN
              note over AN: keyP == publisherP.com
              AN ->> AN: check publisherP.com is allowed to read
              note over AN: keyP is secret and communicated S2S.<br>ok: this is a valid request
              AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
              AN -->> P: "read prebid SSO" URL = ...
          deactivate AN

            P -->> B: REDIRECT
        deactivate P


        activate B
            B ->> O: GET /ENCRYPTED (for "read")
        deactivate B

        activate O
            O ->> O: no 🍪 found

            O ->> AN: (S2S) POST /encrypt<br>url=xxx

          activate AN
              AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
              AN -->> O: "ENCRYPTED_URL" = ...
          deactivate AN

            O -->> B: REDIRECT
        deactivate O

        activate B
            B ->> P: GET /ENCRYPTED
        deactivate B

        activate P

        P ->> AN: (S2S) POST /decrypt<br>APIkey=keyP<br>encrypted=ENCRYPTED

          activate AN
              note over AN: keyP == publisherP.com
              AN ->> AN: check publisherP.com is allowed to read
              AN ->> AN: DECRYPT data<br>with operator0.prebidsso.com private key
              AN -->> P: decrypted data = ...
          deactivate AN

            P ->> P: set 🍪 "val"
            P -->> B: REDIRECT
        deactivate P

        activate B
            B ->> P: GET /pageP.html
        deactivate B

        activate P
            P ->> P: 🍪 "val" found
            P -->> B: REDIRECT to CMP
        deactivate P

        activate B
            B ->> C: GET /cmp.html?afterCmpUrl=publisherP.com/pageP.html
        deactivate B

        activate C
            C ->> AN: (S2S) POST /fetch<br>APIkey=keyC<br>redirectUrl=cmp.com/cmp.html?afterCmpUrl=publisherP.com/pageP.html

          activate AN
              note over AN: keyC == cmp.com
              AN ->> AN: check cmp.com is allowed to read
              AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
              AN -->> C: "read prebid SSO" URL = ...
          deactivate AN

            C -->> B: REDIRECT
        deactivate C

        activate B
            B ->> O: GET /ENCRYPTED (for "read")
        deactivate B

        activate O
            O ->> O: no 🍪 found

            O ->> AN: (S2S) POST /encrypt<br>url=xxx

          activate AN
              AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
              AN -->> O: "ENCRYPTED_URL" = ...
          deactivate AN

            O -->> B: REDIRECT
        deactivate O

        activate B
            B ->> C: GET /ENCRYPTED
        deactivate B

        activate C

            C ->> AN: (S2S) POST /decryptAsJSON<br>APIkey=keyC<br>encrypted=ENCRYPTED

          activate AN
              note over AN: keyP == publisherP.com
              AN ->> AN: check publisherP.com is allowed to read
              AN ->> AN: create ID
              AN ->> AN: SIGN ID<br/>with own private key
              note over AN: ID has been signed by operatorO.prebidsso.com<br/>it can be trusted
              AN ->> AN: DECRYPT data<br>with operator0.prebidsso.com private key
              AN -->> C: decrypted data = ...
          deactivate AN

            C -->> B: display CMP
        deactivate C

        activate B
            B ->> B: JS: show id in form<br>or store in hidden input
            note over B: Note: don't write 🍪 yet, wait for user consent
            B -->> U: 
        deactivate B

    deactivate U

    U ->> B: submit preferences

    activate U
        activate B
            B ->> C: GET /cmp.html?id=xxx&preferences=yyy
        deactivate B

        activate C

            C ->> C: SIGN (preferences + id)<br/>with own private key => sign[pref & id]
            note over C: signature includes id to ensure<br>these preferences are for this user.<br>It can be trusted

            C ->> AN: (S2S) POST /update<br>APIkey=keyC<br>id=xxx&preferences=yyy&signatures=...

            activate AN
                note over AN: keyC == cmp.com
                AN ->> AN: check cmp.com is allowed to write
                AN ->> AN: VERIFY sign[id] with operatorO.prebidsso.com public key
                AN ->> AN: VERIFY sign[pref & id] with cmp.com public key
                note over AN: ok: these preferences are valid<br>and they are associated with the id
                AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
                AN -->> C: update URL = ...
            deactivate AN

            C -->> B: REDIRECT
        deactivate C

        activate B
            B ->> O: GET /ENCRYPTED (for "update")
        deactivate B

        activate O
            O ->> O: write 1P 🍪:<br/>preferences & sign[pref & id]
            note over O: preferences have been signed by cmp<br/>ID has been signed by operatorO.prebidsso.com<br/>both can be trusted
            O ->> O: ENCRYPT URL<br>with operator0.prebidsso.com private key
            O -->> B: REDIRECT
        deactivate O

        activate B
            B ->> P: GET /ENCRYPTED
        deactivate B

        activate P

            P ->> AN: (S2S) POST /decrypt<br>APIkey=keyP<br>encrypted=ENCRYPTED

            activate AN
                note over AN: keyP == publisherP.com
                AN ->> AN: check publisherP.com is allowed to read
                AN ->> AN: DECRYPT data<br>with operator0.prebidsso.com private key
                AN -->> P: decrypted data = ...
            deactivate AN

            P ->> P: write 1P 🍪:<br/>id & sign[id]<br>preferences & sign[pref & id]

            P -->> B: REDIRECT
        deactivate P

        activate B
            B ->> P: GET /pageP.html
        deactivate B

        activate P
            P -->> B: display
        deactivate P

        B -->> U: 

    deactivate U
end

rect rgba(255, 255, 255, .55)
note right of U: Time T2<br>"READ" scenario: user visits a "new" advertiser

    U ->> B: visit www.advertiserA.com/pageA.html
    activate U

        activate B
            B ->> A: GET /pageA.html
        deactivate B

        activate A
            A ->> A: no Prebid SSO ID 🍪 found
            A ->> AN: (S2S) POST /fetch<br>APIkey=keyA<br>redirectUrl=publisherP.com/pageP.html

            activate AN
                note over AN: keyA == advertiserA.com
                AN ->> AN: check advertiserA.com is allowed to read
                note over AN: keyA is secret and communicated S2S.<br>ok: this is a valid request
                AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
                AN -->> A: "read prebid SSO" URL = ...
            deactivate AN

            A -->> B: REDIRECT
        deactivate A


        activate B
            B ->> O: GET /ENCRYPTED (for "read")
        deactivate B

        activate O
            O ->> O: no 🍪 found

            O ->> AN: (S2S) POST /encrypt<br>url=xxx

            activate AN
                AN ->> AN: ENCRYPT URL<br>with operator0.prebidsso.com private key
                AN -->> O: "ENCRYPTED_URL" = ...
            deactivate AN

            O -->> B: REDIRECT
        deactivate O

        activate B
            B ->> A: GET /ENCRYPTED
        deactivate B

        activate A

            A ->> AN: (S2S) POST /decrypt<br>APIkey=keyA<br>encrypted=ENCRYPTED

            activate AN
                note over AN: keyA == advertiserA.com
                AN ->> AN: check advertiserA.com is allowed to read
                AN ->> AN: DECRYPT data<br>with operator0.prebidsso.com private key
                AN -->> A: decrypted data = ...
            deactivate AN

            A ->> A: write 1P 🍪:<br/>id & sign[id]<br>preferences & sign[pref & id]

            A -->> B: REDIRECT
        deactivate A

        activate B
            B ->> A: GET /pageP.html
        deactivate B

        activate A
            A -->> B: display
        deactivate A

        B -->> U: 

    deactivate U
end
Loading