# How to generate delegated identity on server and send to browser

**URL:** <https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334>\
**Category:** JavaScript\
**Tags:** agent, JavaScript, rust, internet-identity\
**Created:** [December 7, 2023, 5:17pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334 "2023-12-07T17:17:31Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rosarp](https://avatars.discourse-cdn.com/v4/letter/r/779978/32.png) [@rosarp](https://forum.dfinity.org/u/rosarp)\
**Post date:** [December 7, 2023, 5:17pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/1 "2023-12-07T17:17:31Z")

</div>

I am trying to make requests on behalf of the user from the server and from the user’s browser using the same principal…  
To achieve this I’m trying following steps.

I have generated Identity on server (axum) for incoming user.  
Using that identity and server’s own ‘Identity’,  
I’m trying to create delegated identity, on the server.  
And I want to use this Delegated Identity from browser, for the user to connect to a canister.

Below is the code for `Axum server` : [Server side code](https://github.com/go-bazzinga/hot-or-not-auth/blob/12c50f06dbb016f5b79ce1bf07a7f9a27a4c64de/src/main.rs#L24)

`Client Identity` Code:

```auto
    let (client_secret, _client_pem) = generate_key("oauth_identity").unwrap();
    let client_identity = Secp256k1Identity::from_private_key(client_secret.clone());

```

`Server Identity` Code:

```auto
    let path = Path::new(SERVER_PEM_FILEPATH);
    let server_identity = Secp256k1Identity::from_pem_file(path).unwrap();

```

Creating `Delegated Identity`:

```auto
....
    let delegation = Delegation {
        pubkey: server_identity.public_key().unwrap(),
        expiration,
        targets: None,
    };
....
    let signature = client_identity.sign_delegation(&delegation).unwrap();
    let signed_delegation = SignedDelegation {
        delegation,
        signature: signature.signature.unwrap(),
    };
....
    let delegated_identity = DelegatedIdentity::new(
        signature.public_key.unwrap(),
        server_identity,
        vec![signed_delegation.clone()],
    );

```

Here I can send to browser, serialized `signed_delegation`. However `delegated_identity` is not serializable.  
 → Which means, using the signed\_delegation, I need to create identity on the browser again. Need help with this, as I see either the approach is not feasible or I’m missing something.

Code on `browser` side: [Frontend code](https://github.com/go-bazzinga/hot-or-not-auth/blob/12c50f06dbb016f5b79ce1bf07a7f9a27a4c64de/verify_principal/src/verify_principal_frontend/src/index.js#L40)

```auto
import { verify_principal_backend } from "../../declarations/verify_principal_backend";
import { DelegationIdentity, DelegationChain } from "@dfinity/identity";
....
const delegationChain = DelegationChain.fromJSON(signed_delegation);
// below method needs a identity, will it be newly generated identity?
const clientIdentity = Secp256k1KeyIdentity.generate();                                                                  
const delegatedIdentity = DelegationIdentity.fromDelegation(clientIdentity, delegationChain);
// call to canister
await verify_principal_backend.get_principal_id();

```

With above code, there is error: `Invalid delegations. ` on below line:

```auto
const delegationChain = DelegationChain.fromJSON(signed_delegation);

```

Here above, as there is no identity coming from server, clientIdentity needs to be creatd on browser side to create delegated identity. Will this work? Or there is another way?

Is there any way to create delegated identity on server and pass it for usage to browser?

---

<div class="post-metadata">

**Author:** ![saikatdas0790](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/saikatdas0790/32/17147_2.png) [@saikatdas0790](https://forum.dfinity.org/u/saikatdas0790)\
**Post date:** [December 11, 2023, 5:32am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/2 "2023-12-11T05:32:28Z")

</div>

@frederikrothenberger @nmattia

Any thoughts on this? Happy to clarify our use case further.

The main point where we are stuck is to figure out if delegation identities can be generated on the server where the private keys reside and share with different client devices for making calls to the IC network with the expectation that the IC canister sees the same principal from calls from different client devices.

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [December 11, 2023, 9:47am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/3 "2023-12-11T09:47:06Z")

</div>

Hi @rosarp & @saikatdas0790

The point of using delegations is that you can _delegate_ from one key to another.

I.e. the flow should always be:

1. Generate key pair on the client
2. Send public key to server
3. Create signed delegation on public key
4. Send delegation back to client
5. Use identity on client

If you were to create the complete identity on the server, this would mean transferring also the private key. This is **not recommended** because it is less secure than the above protocol.

Is there a reason why the above flow is not suitable in your case?

Btw. I just noticed, when glancing at the code, that you named the identity “oauth identity”. Just FYI, we have a design for how to authenticate against the IC using OAuth that does not entail storing private keys in a trusted Web2 server (only works if the IC part is the _client_).  
Let me know, if this would be interesting for you.

---

<div class="post-metadata">

**Author:** ![saikatdas0790](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/saikatdas0790/32/17147_2.png) [@saikatdas0790](https://forum.dfinity.org/u/saikatdas0790)\
**Post date:** [December 11, 2023, 10:35am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/4 "2023-12-11T10:35:14Z")

</div>

Yeah, we’d love to talk about what that design enables and how we could utilize it. Our main needs are twofold:

- being able to integrate any identity provider be it Web2 like Google, Apple, FB, etc. or Web3 like Metamask or Internet Identity as a user authentication mechanism
- generate tokens/delegations that can be used to make requests on the user’s behalf both from any client devices that the user might be using (webapp, native mobile app) or from the server for SSR

Tie this all to a single unique user identity that uniquely identifies a user across the entire Hot or Not network

Let me know if that clarifies. We are happy to jump on a call to discuss this further or ping you on Slack to discuss more.

Let us know 🙂

---

<div class="post-metadata">

**Author:** ![saikatdas0790](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/saikatdas0790/32/17147_2.png) [@saikatdas0790](https://forum.dfinity.org/u/saikatdas0790)\
**Post date:** [December 11, 2023, 10:40am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/5 "2023-12-11T10:40:43Z")

</div>

Quick question,  
For Step 1, would it to be possible to generate the key pair on the server for the client and share it with the client for further usage and storage?

That way, on first request, the server could also fetch required data on the user’s behalf, generate HTML and serve the client all the data it needs for a faster initial render

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [December 11, 2023, 12:26pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/6 "2023-12-11T12:26:21Z")

</div>

To make SSR work, you do not need to send a private key to the client.

Given the backend / canister controls an identity that can be used to sign delegations, the same identity can also be used to call other resources (simply without a delegation).

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 20, 2024, 12:27pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/7 "2024-03-20T12:27:19Z")

</div>

> [@frederikrothenberger](#):
>
> we have a design for how to authenticate against the IC using OAuth that does not entail storing private keys in a trusted Web2 server (only works if the IC part is the _client_).

I would be interested in this. I was evaluating [https://web3auth.io/](https://web3auth.io/) as an alternative.

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [March 20, 2024, 12:50pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/8 "2024-03-20T12:50:48Z")

</div>

@ilbert: Find below a very concise summary of the design. Let me know if you need more information. Ideally we would build a reference implementation of that flow, but currently we do not have one.

1. The dapp front-end generates a session public/private key pair
2. The dapp initiates an OpenID Connect authentation flow with response\_type=id\_token and the `nonce` set to the public key generate in step 1.
3. When the OpenID Connect flow completes (i.e. the user is redirected back to the dapp) it then makes a canister call to the back-end with the `id_token` received from the authorization server to complete authentication. The authentication succeeds if:
  - The `sub` claim must match the subject registered on the canister (or otherwise this must be considered a new user)
  - The `iat` claim must not be too old (e.g. 10 minutes)
  - The `aud` & `azp` claims must match the application id as registered with the OpenID Connect authorization server
  - The signature on the ID token must be valid and signed with a well known authorization server public key. Can most likely be fetched using HTTP outcalls from the JSON Web Key Set (JWKS) endpoint.
  - The `nonce` claim must correspond to the public key used to make the call, i.e the self authenticating principal of the key included in `nonce` is equal to the `caller`

If step 3 succeeds, the canister should associate the `caller` principal with the user matching the `sub` claim for the duration of a reasonable session. Alternatively, the canister can also issue a delegation to a principal associated with the user profile on the public key. The delegation has has an `expiration` and hence relieves the canister from checking session expiry itself.

I hope this helps.

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 20, 2024, 1:02pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/9 "2024-03-20T13:02:09Z")

</div>

> [@frederikrothenberger](#):
>
> The `sub` claim must match the subject registered on Internet Identity (or otherwise this must be considered a new user)

Does this mean that the session key pair generated at step 1. must be delegated by the II of the user?

> [@frederikrothenberger](#):
>
> Alternatively, the canister can also issue a delegation to a principal associated with the user profile on the public key.

How can the canister issue a delegation in this case?

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 20, 2024, 1:12pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/10 "2024-03-20T13:12:55Z")

</div>

My objective is to give my web2 users (which likely don’t want to deal with II and will interact via a React Native mobile application with my platform) the login experience they’re used to (email/password, social providers, phone number, etc.), while also authenticating and identifying them on the backend canister.

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [March 20, 2024, 1:29pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/11 "2024-03-20T13:29:26Z")

</div>

> > The `sub` claim must match the subject registered on Internet Identity (or otherwise this must be considered a new user)
> 
> Does this mean that the session key pair generated at step 1. must be delegated by the II of the user?

Sorry, this was a copy / paste error from an internal (II specific) document. The design is completely independent of Internet Identity. I have edited my post above.

> > Alternatively, the canister can also issue a delegation to a principal associated with the user profile on the public key.
> 
> How can the canister issue a delegation in this case?

For that to work, your canister needs to assign each new user a principal derived from a [canister signature](https://internetcomputer.org/docs/current/references/ic-interface-spec/#canister-signatures) public key of your canister. The canister then needs to associate the `sub` claim from the `id_token` to that principal.

Then, the canister can issue delegations on the session public key (supplied by the client as `nonce` in the `id_token`), by creating a canister signature. This is very similar to how II works, see code [here](https://github.com/dfinity/internet-identity/blob/90c8902a2aae5b2a6ba1047ca2032f793f82378f/src/internet_identity/src/delegation.rs#L23).

> My objective is to give my web2 users (which likely don’t want to deal with II and will interact via a React Native mobile application with my platform) the login experience they’re used to (email/password, social providers, phone number, etc.), while also authenticating and identifying them on the backend canister.

Yes, this is exactly what the above design achieves. Sorry for the confusion caused by the copy / paste error.

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 20, 2024, 2:37pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/12 "2024-03-20T14:37:47Z")

</div>

> [@frederikrothenberger](#):
>
> For that to work, your canister needs to assign each new user a principal derived from a [canister signature](https://internetcomputer.org/docs/current/references/ic-interface-spec/#canister-signatures) public key of your canister. The canister then needs to associate the `sub` claim from the `id_token` to that principal.

So basically, as you said, the logic is almost the same as on the II, but in this case we use the `sub` claim instead of the user anchor to identify the user and issue the delegation accordingly, right?

> [@frederikrothenberger](#):
>
> Yes, this is exactly what the above design achieves. Sorry for the confusion caused by the copy / paste error.

Amazing! I’ll give it some tries and eventually post updates here 😉

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [March 20, 2024, 2:56pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/13 "2024-03-20T14:56:05Z")

</div>

> [@ilbert](#):
>
> So basically, as you said, the logic is almost the same as on the II, but in this case we use the `sub` claim instead of the user anchor to identify the user and issue the delegation accordingly, right?

Yes, exactly.

> [@ilbert](#):
>
> Amazing! I’ll give it some tries and eventually post updates here 😉

Looking forward to that! 🙂

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 22, 2024, 2:55pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/14 "2024-03-22T14:55:06Z")

</div>

@frederikrothenberger is there a more generic example or guide out there on how to issue delegations from canister signatures?  
I feel like I have to copy&paste the relevant parts of the II source code and adapt them to my canister, which is something that can likely introduce bugs and debts…

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [March 22, 2024, 3:00pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/15 "2024-03-22T15:00:39Z")

</div>

@ilbert: You can also take a look at [GitHub - kristoferlund/ic-siwe: Integrating Ethereum apps with Internet Computer via SIWE, focusing on secure, seamless cross-chain interactions.](https://github.com/kristoferlund/ic-siwe), which has the same implementation as well. Maybe it has less II specific clutter around it…

But I don’t know of an example that has the delegation logic _only_. It might be worth creating a library for that. 😉

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 28, 2024, 9:33am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/16 "2024-03-28T09:33:47Z")

</div>

> **[GitHub - ilbertt/ic-react-native-jwt-auth: React Native (Expo) + JWT...](https://github.com/ilbertt/ic-react-native-jwt-auth)**
>
> React Native (Expo) + JWT Authentication + Rust canister - ilbertt/ic-react-native-jwt-auth

I’ve published a demo repository that has the following components:

- React Native mobile app (with [Expo](https://expo.dev/)): [src/app](https://github.com/ilbertt/ic-react-native-jwt-auth/tree/main/src/app)
- off-chain backend (JS): [src/app\_backend](https://github.com/ilbertt/ic-react-native-jwt-auth/tree/main/src/app_backend)
- IC Rust backend canister: [src/ic\_backend](https://github.com/ilbertt/ic-react-native-jwt-auth/tree/main/src/ic_backend)
- [Auth0](https://auth0.com/) authentication provider

I’ll update the README to include more details.

The backend canister can successfully verify the `id_token` and issue delegations.

I’ve used the [canister\_sig\_util](https://github.com/dfinity/internet-identity/tree/release-2024-03-22/src/canister_sig_util) crate from the Internet Identity repo, which helps me with the signatures map.

@frederikrothenberger I have a question: how should the **salt** be handled across upgrades? I’ve tried upgrading the canister, which triggers fetching the salt again from the `raw_rand` api and this results in different delegations for the same user `sub`.

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [March 28, 2024, 9:42am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/17 "2024-03-28T09:42:10Z")

</div>

@ilbert: Very nice! Did you deploy this somewhere as a demo?

Store the `salt` in stable memory, that way it is persisted across upgrades.

---

<div class="post-metadata">

**Author:** ![ilbert](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/ilbert/32/8717_2.png) [@ilbert](https://forum.dfinity.org/u/ilbert)\
**Post date:** [March 28, 2024, 10:51am UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/18 "2024-03-28T10:51:07Z")

</div>

> [@frederikrothenberger](#):
>
> Did you deploy this somewhere as a demo?

Still not and not sure if I ever will, since the JWT validation on the canister depends on my Auth0 tenant and the mobile app is not easily publishable. I anyway still have to implement some things like the JSON Web Key Set fetching via HTTPS Outcall.

I thought it could be more like a template for anyone who wants to implement something similar.

> [@frederikrothenberger](#):
>
> Store the `salt` in stable memory, that way it is persisted across upgrades.

I guess the II canister is doing the same, right?

* * *

Another question: is it ok to authorize the user based on the `id_token` in both the [prepare\_delegation](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/lib.rs#L77) and [get\_delegation](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/lib.rs#L101) endpoints? Both endpoints use the [check\_authorization](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/lib.rs#L59) function.

---

<div class="post-metadata">

**Author:** ![frederikrothenberger](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/frederikrothenberger/32/3826_2.png) [@frederikrothenberger](https://forum.dfinity.org/u/frederikrothenberger)\
**Post date:** [March 28, 2024, 1:09pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/19 "2024-03-28T13:09:18Z")

</div>

> > [quote=“frederikrothenberger, post:17, topic:25334”]  
> > Did you deploy this somewhere as a demo?  
> > [/quote]
> 
> Still not and not sure if I ever will, since the JWT validation on the canister depends on my Auth0 tenant and the mobile app is not easily publishable. I anyway still have to implement some things like the JSON Web Key Set fetching via HTTPS Outcall.

Yes, I understand. But I think we should definitely give this project some visibility as it is a very useful piece of code for other projects. @domwoe maybe include it in [awesome ICP](https://github.com/dfinity/awesome-internet-computer)?

> Another question: is it ok to authorize the user based on the `id_token` in both the [prepare\_delegation](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/lib.rs#L77) and [get\_delegation](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/lib.rs#L101) endpoints? Both endpoints use the [check\_authorization](https://github.com/ilbertt/ic-react-native-jwt-auth/blob/882539addd4e0e35fe1f1756701296f1ff085239/src/ic_backend/src/lib.rs#L59) function.

It is enough to just do that in the `prepare_delegation` call. The prepare delegation call creates a link between the `sub` claim and the `session_key`. At this point the canister creates the canister signature.

For `get_delegation` it is sufficient simply check that the `caller` is `session_principal` (corresponding to `session_key`). For any other `caller` the `delegation` is useless anyway as it delegates to the `session_key` specifically.

---

<div class="post-metadata">

**Author:** ![domwoe](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/domwoe/32/5165_2.png) [@domwoe](https://forum.dfinity.org/u/domwoe)\
**Post date:** [March 28, 2024, 8:39pm UTC](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334/20 "2024-03-28T20:39:47Z")

</div>

> [@frederikrothenberger](#):
>
> @domwoe maybe include it in [awesome ICP](https://github.com/dfinity/awesome-internet-computer)?

yep, we should at least add it there, but I asked @ilbert to add a bit more information and a sequence diagram to the readme first.

[Next page](https://forum.dfinity.org/t/how-to-generate-delegated-identity-on-server-and-send-to-browser/25334.md?page=2)
