Skip to content

NIP-98 HTTP Auth#469

Merged
v0l merged 6 commits intonostr-protocol:masterfrom
v0l:nip98
Jun 17, 2023
Merged

NIP-98 HTTP Auth#469
v0l merged 6 commits intonostr-protocol:masterfrom
v0l:nip98

Conversation

@v0l
Copy link
Copy Markdown
Member

@v0l v0l commented Apr 24, 2023

Adding NIP-98 for HTTP Auth

This is currently used by the Snort backend api for managing NIP-5 addresses and the subscriptions system.

Nosdav is also using this spec @melvincarvalho

https://github.com/v0l/nips/blob/nip98/98.md

@melvincarvalho
Copy link
Copy Markdown

@staab
Copy link
Copy Markdown
Member

staab commented Apr 24, 2023

How is the event delivered to the API? Is it published to a relay? I would be concerned about replay attacks, this doesn't seem secure. I don't understand why a direct request wouldn't work, is this for delegating authentication?

@v0l
Copy link
Copy Markdown
Member Author

v0l commented Apr 24, 2023

How is the event delivered to the API? Is it published to a relay?

Authorization header is a request header in HTTP

I would be concerned about replay attacks

Idempotency can be managed by the API and is not a concern for this spec, timestamp checks should be good enough in most cases.

@staab
Copy link
Copy Markdown
Member

staab commented Apr 24, 2023

Ah, ok, I missed that. LGTM I guess then. This is a criticism of zaps as well, but it's strange to use the standard event structure but then encode it and throw it in some other place like a query string or authentication header rather than just using a regular HMAC or signing the url you're requesting directly or whatnot. Putting it all in a valid event makes me worry that a confused client will publish this event, which contains sensitive information, to relays, which is possible and definitely not what you want to do.

@v0l
Copy link
Copy Markdown
Member Author

v0l commented Apr 24, 2023

The main reason for using nostr events is that we already have infrastructure to create signed payloads via NIP-7.

Suggesting something like regular HMAC auth would require access to private keys or changes to NIP-7, we have a JSON object which is similar to JWT here and i see an opportunity to re-use the nostr identity in external systems over regular HTTP requests.

I would even go so far as to say that this should be used instead of NIP-42! Its much cleaner to auth to relays this way.

@fiatjaf
Copy link
Copy Markdown
Member

fiatjaf commented Apr 26, 2023

Is this the spec we want for all "Nostr login" use cases?

@fiatjaf
Copy link
Copy Markdown
Member

fiatjaf commented Apr 26, 2023

@Dolu89 @lukechilds can you take a look at this?

@nohea
Copy link
Copy Markdown

nohea commented Apr 27, 2023

It's interesting reading this proposal, coming from some slight use of JWTs with shared secrets on servers.
JWTs typically have an auth provider authenticating a user and also validating "claims" (authorization roles).
The JWT is passed in the Authorization Bearer _ HTTP header along with the actual resource request.
The server can then validate identity and claims via symmetrical shared secret, or alternatively via jwk_url for asymmetric auth.

Clearly for Nostr we want to auth users asymmetrically. It is technically possible for Nostr clients to generate their own JWT for id. To validate permissions to a resource, an organization would have to run their own auth service, use Nostr to validate id, but add claims to the JWT.

Wrapping the auth+httprequest in a Nostr event adds extra overhead. Clearly it works, but figuring out auth via the existing JWT methods will allow for more services to use Nostr auth without customization.

@blakejakopovic
Copy link
Copy Markdown
Contributor

Is this the spec we want for all "Nostr login" use cases?

@fiatjaf This suits my needs for web app login and server sessions. We can close #373

@arthurfranca
Copy link
Copy Markdown
Contributor

Nice NIP but I wonder why here there is no challenge need but NIP-42 required it? (NIP-42 became a lot less attractive after the challenge requirement)

On NIP-42 I suggested an authorization on connection with something like new WebSocket("wss://...?authorization=stringified_22242_event") (query string cause websocket doesn't play well with headers) but it got rejected because of #141 comment from @cameri .

@quentintaranpino
Copy link
Copy Markdown

I just implemented it in nostrcheck-api-ts it seems to me a very elegant solution to authenticate a request to a public API.

Thanks @v0l 🙂

@blakejakopovic
Copy link
Copy Markdown
Contributor

Have we considered including notes for common HTTP request failure responses? Effectively returning 401 Unauthorised or 402 Payment Required would be reasonable to use - maybe others could be considered too.

For either of those responses, we could perhaps define a WWW-Authenticate header with a Nostr specific auth-scheme to indicate this method of auth is supported.

As an example:

WWW-Authenticate: <auth-scheme>
WWW-Authenticate: Nostr-NIP-98

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/WWW-Authenticate
https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes

@fiatjaf
Copy link
Copy Markdown
Member

fiatjaf commented May 8, 2023

I wonder the same, @arthurfranca.

@melvincarvalho
Copy link
Copy Markdown

I wonder the same, @arthurfranca.

Implementing a challenge in the authentication process can provide additional security, such as protection against replay attacks and ensuring request freshness, it may be overkill for the method described in NIP-98. Here are a few reasons why:

  1. The method already includes several robust security measures, such as checking the kind, created_at, url, and method tags, which help ensure the authenticity and integrity of the request.

  2. The use of a timestamp within the created_at tag, combined with the server's requirement to validate it within a reasonable time window, helps mitigate the risk of replay attacks without the need for a separate challenge.

  3. The method is primarily designed for Nostr-specific HTTP services, which may have lower risk profiles than more general-purpose applications. In this context, the existing security measures might suffice.

  4. Adding a challenge-response mechanism can introduce complexity and increase the time required for authentication. This might negatively impact the user experience and performance, especially if the benefits do not outweigh the added complexity.

While a challenge can provide additional security benefits, it may not be strictly necessary for the method described in NIP-98. The existing security measures appear sufficient to address the primary risks. However, if there is a need for enhanced security in the future, a challenge-response mechanism could be considered as an optional or additional feature.

@fiatjaf
Copy link
Copy Markdown
Member

fiatjaf commented May 10, 2023

@melvincarvalho do you understand why it is absolutely necessary for NIP-42 and not for this? I'm asking honestly because I forgot. For NIP-42 I think it wasn't just providing "extra security", it was absolutely necessary.

@blakejakopovic
Copy link
Copy Markdown
Contributor

@fiatjaf as an example of prior work that includes a challenge, the lightning lud-04 spec includes a k value. Effectively making it an interactive protocol.

I just watched the Fedimint schnorr signature tech talk, and they mentioned it's possible to do this non-interactively where you effectively use a zero-knowledge proof (using a provably random number as I understand it) instead of a challenge/interactive protocol. I'm waiting for the slides to be posted, as I don't have a full description of how it functions.

For protocol based NIPs, if may be useful to include a diagram to make it clear. Something like this perhaps.


ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication

@mikedilger
Copy link
Copy Markdown
Contributor

mikedilger commented May 11, 2023

The challenge is to avoid replay attacks. In NIP-42 an impostor can send an event created by someone else and the relay will believe the impostor is that someone else. In this NIP-98, an imposter can do the same thing (within the suggested 60 seconds).

Under normal usage impostors won't have access to the authenticating event. But in case they do through some other security weakness, it should only be usable once. This is for security-in-depth.

If an interactive protocol is intolerable, then we should be looking at zk-SNARK (although I'm not sure it provides the no-replay freshness guarantee we are looking for)

@Egge21M
Copy link
Copy Markdown
Contributor

Egge21M commented May 11, 2023

Under normal usage impostors won't have access to the authenticating event. But in case they do through some other security weakness, it should only be usable once. This is for security-in-depth.

I think I disagree here. Most authentication services have this problem. If you leak your JWT your have a problem until it expires. 60 seconds is much shorter than most token expiries.

And if most people consider this a problem, servers could store the id of the event, similar to how oath keeps track of used tokens, and forbid reuse. It would mean that the client will have to rebuild events for every subsequent request though, which sounds undesirable

@fiatjaf
Copy link
Copy Markdown
Member

fiatjaf commented May 11, 2023

The challenge is to avoid replay attacks. In NIP-42 an impostor can send an event created by someone else and the relay will believe the impostor is that someone else.

How? If the user Bob sends his event directly to the relay Ronald, and the event has a commitment to the relay URL, what can Ronald do with that? It can't use that to auth to other relays.

@blakejakopovic
Copy link
Copy Markdown
Contributor

blakejakopovic commented May 11, 2023 via email

@mikedilger
Copy link
Copy Markdown
Contributor

How? If the user Bob sends his event directly to the relay Ronald, and the event has a commitment to the relay URL, what can Ronald do with that? It can't use that to auth to other relays.

Ronald being the relay can't do anything interesting. But any 3rd party getting ahold of it could trick Ronald.

@fiatjaf
Copy link
Copy Markdown
Member

fiatjaf commented May 12, 2023

Should we change NIP-42 to remove the challenge? @mikedilger That would make it much simpler.

@arthurfranca
Copy link
Copy Markdown
Contributor

  1. The method already includes several robust security measures, such as checking the kind, created_at, url, and method [...] help ensure the authenticity and integrity of the request.

Same as NIP-42.

  1. The use of a timestamp within the created_at tag [...] within a reasonable time window

Same as NIP-42. (It is suggested 10 min but it could also be 60 seconds)

  1. The method is primarily designed for Nostr-specific HTTP services, which may have lower risk profiles [...]

Relays (NIP-42 use-case) have even lower risk cause not only the auth event is signed, but all other payloads are signed events that a malicious client wouldn't be able to create without a nsec

  1. Adding a challenge-response mechanism [...] negatively impact the user experience [...]

Totally agree! Also for NIP-42.


NIP-98 main difference is that on every request, a new auth event is created.
While on NIP-42 it is created just once, cause it is a persistent websocket connection.

To be clear, I'm in favor of not using a challenge for both NIPs. NIP-42 should be as easy as new WebSocket("wss://...?authorization=stringified_22242_event") -> close the socket if authentication fail -> or register pubkey to ws client instance

@mikedilger
Copy link
Copy Markdown
Contributor

mikedilger commented May 13, 2023

Should we change NIP-42 to remove the challenge? @mikedilger That would make it much simpler.

No. I'm not following your gist here. NIP-42 and NIP-98 need challenges.

The challenge in NIP-42 is needed. The attack is like this:

  1. Bob connects to Ronald.
  2. Ronald asks Bob for AUTH not requiring any challenge
  3. Bob authenticates. But Eve was evesdropping and copied the auth event from bob.
  4. Eve connects to Ronald.
  5. Ronald asks Eve for AUTH not requiring any challenge
  6. Eve presents the event that Bob generated. Ronald now thinks Eve is Bob.

Even with AUTH (but without wss) there is a session-hijacking attack where Eve can hijack the session and Ronald thinks he is continuing to talk with Bob, but it is now Eve. So NIP-42 should require WSS, not just WS.

@melvincarvalho
Copy link
Copy Markdown

Your concern is valid, and you've illustrated a potential vulnerability of a session-hijacking attack via eavesdropping, which is indeed a risk when not using a challenge-response authentication or not using a secure protocol such as WSS.

However, let me clarify that non-challenge signed headers can still be safe if implemented with proper measures. Here's how:

  1. Using Secure Communication Channels: When the communication between the parties happens over secure channels like WSS (WebSocket Secure) instead of WS (WebSocket), the session is encrypted. So, even if Eve is eavesdropping, she won't be able to interpret the exchanged data, making it difficult to hijack the session.

  2. Timestamping and Nonce: Adding a timestamp or a nonce (a number used once) in the authentication header could prevent replay attacks. Even if Eve captures Bob's authenticated event, she cannot reuse it because the timestamp or nonce will not be valid anymore.

  3. Short-lived Tokens: The authentication event generated by Bob could include a short-lived token. Once the token expires, it cannot be used for authentication. This means that even if Eve captures the authentication event, she has a limited time to use it, reducing the window of opportunity for the attack.

  4. IP Binding: The session could be bound to the IP address from which the original authentication event came. If Eve tries to use Bob's event, the IP address won't match, and the session won't be hijacked.

On idempotent operations like GET and PUT, non-challenge signed headers are generally safe because these operations can be performed multiple times without different outcomes.

Idempotency here means that making the same request once or multiple times results in the same state on the server. So, even if an attacker like Eve manages to replay Bob's request, it wouldn't lead to unintended consequences, as the state of the server would remain the same.

However, for non-idempotent operations like POST, where each request could lead to a different outcome (for instance, creating a new resource each time), the replay attack risk is significantly higher. In these cases, incorporating a nonce in your authentication protocol can help safeguard against such replay attacks.

When a client makes a request, it includes a unique nonce. The server keeps track of all used nonces and does not accept requests with nonces that have already been used. This way, even if Eve captures and attempts to replay Bob's request, the server would reject it because the nonce has already been used.

@mikedilger
Copy link
Copy Markdown
Contributor

I agree that WSS prevents session hijacking.

I'm no fan of trusting in "short-lived". Eve can attack microseconds after. Anything the legitimate user could do, the attacker could do.

A nonce could work, but that means the server has to remember every nonce. If you think that is easier than the server issuing a challenge, then ok. But they have to be tracked forever, kind of like an ever growing blockchain. I should presume bitcoiners are fine with that craziness.

I hear you on idempotent operations. Replaying such is not a risk if they truly are fully idempotent.

IP binding isn't secure. Kevin Mitnick attacked Tsusomu Shimumora's lab using half-open TCP connections that spoofed the IP address... way back when I was learning computer security in 1994 or so.

@Egge21M
Copy link
Copy Markdown
Contributor

Egge21M commented May 13, 2023

A nonce could work, but that means the server has to remember every nonce. If you think that is easier than the server issuing a challenge, then ok. But they have to be tracked forever, kind of like an ever growing blockchain. I should presume bitcoiners are fine with that craziness.

It would only have to be kept until the timestamp goes out of the allowed timeframe

@arthurfranca
Copy link
Copy Markdown
Contributor

arthurfranca commented May 13, 2023

  1. Timestamping and Nonce: Adding a timestamp or a nonce (a number used once) in the authentication header could prevent replay attacks.

A nonce could work, but that means the server has to remember every nonce.

The nonce is the event id. Just need to keep it around for the allowed time window (60 seconds).

IP binding isn't secure [...] Kevin Mitnick [...] spoofed the IP address [...]

For using the same ip on an http connection I only imagine it possible if using the same local network (like same lan house) or hacking the user ISP, but I'm not Kevin Mitnick xD. Atleast it is an extra security layer.


Regarding a NIP-42 version without challenge (NIP-98 doesn't need it as it is not a persistent session - just keep track of event id), the relay could do the AUTH command dance (the current NIP-42 with challenge) when something important is at stake.
Like when you are already logged in but have to send the current password again when wanting to change the password. For nostr it would be after user tries to do NIP-109: Pubkey Deletion, for instance.
<- it doesnt even make sense cause attacker would need the nsec to create the event. so can't think of an use-case for challenge

So NIP-42 is overkill and has poor experience for the current use-cases (rate-limiting and [paid] relay login). For session creation, an authentication without challenge is good enough.

4. The `method` tag MUST be the same HTTP method used for the requested resource.

When the request contains a body (as in POST/PUT/PATCH methods) clients SHOULD include a SHA256 hash of the request body in a `payload` tag as hex (`["payload", "<sha256-hex>"]`), servers MAY check this to validate that the requested payload is authorized.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When calling an [unsafe](https://developer.mozilla.org/en-US/docs/Glossary/Safe/HTTP) http method (all but GET, HEAD and OPTIONS), server SHOULD keep track of the event id for the above time window duration to prevent reuse.

```
Authorization: Nostr eyJpZCI6ImZlOTY0ZTc1ODkwMzM2MGYyOGQ4NDI0ZDA5MmRhODQ5NGVkMjA3Y2JhODIzMTEwYmUzYTU3ZGZlNGI1Nzg3MzQiLCJwdWJrZXkiOiI2M2ZlNjMxOGRjNTg1ODNjZmUxNjgxMGY4NmRkMDllMThiZmQ3NmFhYmMyNGEwMDgxY2UyODU2ZjMzMDUwNGVkIiwiY29udGVudCI6IiIsImtpbmQiOjI3MjM1LCJjcmVhdGVkX2F0IjoxNjgyMzI3ODUyLCJ0YWdzIjpbWyJ1cmwiLCJodHRwczovL2FwaS5zbm9ydC5zb2NpYWwvYXBpL3YxL241c3AvbGlzdCJdLFsibWV0aG9kIiwiR0VUIl1dLCJzaWciOiI1ZWQ5ZDhlYzk1OGJjODU0Zjk5N2JkYzI0YWMzMzdkMDA1YWYzNzIzMjQ3NDdlZmU0YTAwZTI0ZjRjMzA0MzdmZjRkZDgzMDg2ODRiZWQ0NjdkOWQ2YmUzZTVhNTE3YmI0M2IxNzMyY2M3ZDMzOTQ5YTNhYWY4NjcwNWMyMjE4NCJ9
```

Copy link
Copy Markdown
Contributor

@mikedilger mikedilger May 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replay Attacks

While this NIP assures that the kind 27235 event guarantees that its author authorizes using the stated HTTP method at the stated HTTP URL within 60 seconds of the created_at timestamp, it does not guarantee to the relay server that the HTTP client supplying this event is the author of that event. That is to say, replay attacks within 60 seconds are possible if the event leaks.

Relays Servers should consider whether any data they return to an authenticated HTTP connection is confidential. If so, it is strongly recommended that they only accept authentication and reply with said confidential information if the connection is secured with TLS (e.g. via https).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no relays involved in this flow. It only signs an event to take advantage of NIP-07, but the result is sent over an HTTP header.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A 60 second expiring token scoped to a specific URL is actually significantly better security than OAuth tokens, even with refresh tokens.

This is perhaps the most secure HTTP Auth method the world has ever seen.

@melvincarvalho
Copy link
Copy Markdown

Another implementation with zapgate

@alexgleason
Copy link
Copy Markdown
Member

This is interesting. I needed to create server-side events on behalf of users, and I solved a similar problem differently:

  1. Client opens a websocket connection to the server.
  2. Client uses a pubkey in the Authorization header when making an HTTP request.
  3. The server does not immediately serve a response. It stalls.
  4. Server pushes an event to sign to the client over the websocket.
  5. Client signs the event and pushes it back to the server.
  6. The server finally returns the HTTP response.

I have a very specific use-case (hacking Nostr support into a legacy system), but I thought you might think it's interesting.

"created_at": 1682327852,
"tags": [
[
"u",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why "u" instead of "url"? I think single letter tags are meant to be indexed by relays with filters such as { "#u": [...] }

Since the intention is not to index, I don't think it should be a single letter.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second this. I believe r would also be valid here.

98.md Outdated
Servers MUST perform the following checks in order to validate the event:
1. The `kind` MUST be `27235`.
2. The `created_at` MUST be within a reasonable time window (suggestion 60 seconds).
3. The `url` tag MUST be exactly the same as the absolute request URL (including query parameters).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you've called it "url" even though your example says "u", so I'm guessing you were trying to decide.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea i prefer url @melvincarvalho prefers u

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@melvincarvalho is wrong. 😃 That's my only remaining feedback, otherwise LGTM.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out. Indeed, we've previously discussed this and arrived at a consensus to use "u", rather than, "url"/"uri". Revisiting this decision would require effort since its already implemented, without providing substantial benefits.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using it on two endpoints, but I would have no problem changing it. I'll adapt to what you all decide 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have anchored this version to NAV-03 to ensure stability even if future changes occur, and have stated that NAV-03 is "based on NIP-98".

NAV-03

There are compelling reasons for using "u" instead of "url", which will become clearer as NosDAV progresses towards the stable 0.1 version. Sincerely hope that this work will not necessitate a breaking change at this point.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I support this NIP. 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hate to bring this back up, but NIP 12 defines r for url references. url is used in NIP 94. Adding u violates rule #4 for drafting NIPs. I think your implementation should lose vs the NIPs repo @melvincarvalho.

Copy link
Copy Markdown
Member

@fiatjaf fiatjaf May 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@staab but the same tag can have different meanings in two different contexts.

@alexgleason
Copy link
Copy Markdown
Member

Another possible flow uses NIP-07's encrypt functionality. The server has a pubkey, which at some point the client obtains and stores. The Authorization header contains the user's pubkey in plaintext, along with a signed message to the server's pubkey.

I've been thinking about this problem a lot.

@blakejakopovic
Copy link
Copy Markdown
Contributor

I've drafted a protocol flow NIP for 401 Unauthorized and 402 Payment Required. I think it should become part of this NIP - as defining a protocol without clear lifecycle and having common uses defined, we will result in weird behaviours between implementations. https://gist.github.com/blakejakopovic/fe384b8fd97231ece267bf264eb466ef - feedback welcome.

I think the best way forward is to define optional additional security layers that can be used. One could be tracking event_id and limiting to single use. Another would be using certificate pinning inside your application, to prevent ssl stripping / MIM. Ultimately we need a non-interactive auth protocol, and optionally an interactive one if people so desire. You can always add additional security like in #469 (comment)

For an ephemeral event, the tag shouldn't matter as it's not going to be indexed anyway (u or url) - what we should do however is try define a standardised tag for urls going forward. However, really it's contextual anyway.

@melvincarvalho
Copy link
Copy Markdown

401 and 402 are a good idea, but I think it should be a separate NIP that builds on this one. Not every NIP-98 implementer will want to implement 402, and there are also numerous ways to do 402 that exist. Adding on 402 may be slow down merging of a NIP that has growing implementations.

How about extension of nip-98 as new nips 98x -- 980, 981, 982 etc.

@blakejakopovic
Copy link
Copy Markdown
Contributor

blakejakopovic commented May 21, 2023 via email

@melvincarvalho
Copy link
Copy Markdown

melvincarvalho commented May 21, 2023

@blakejakopovic I dont think they should be closely coupled. For example in NosDAV nip-98 is already implemented and i use it on an hourly basis

NosDAV is probably going to go in the direction of WebAccessControl and there are many standards for working with 401s 402s and 403s. Have a look for example as casbin.

Implementations that want only the login, should not be forced to take other optional items. But if they were presented as other NIPs they could be taken as needed. Implementations would be further ahead if this NIP were approved, and adding more things to it will push that time line out further.

Copy link
Copy Markdown
Member

@staab staab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK, but I'd prefer to not see u introduced. We only have 26 letters.

"created_at": 1682327852,
"tags": [
[
"u",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I second this. I believe r would also be valid here.

98.md Outdated
Servers MUST perform the following checks in order to validate the event:
1. The `kind` MUST be `27235`.
2. The `created_at` MUST be within a reasonable time window (suggestion 60 seconds).
3. The `url` tag MUST be exactly the same as the absolute request URL (including query parameters).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hate to bring this back up, but NIP 12 defines r for url references. url is used in NIP 94. Adding u violates rule #4 for drafting NIPs. I think your implementation should lose vs the NIPs repo @melvincarvalho.


When the request contains a body (as in POST/PUT/PATCH methods) clients SHOULD include a SHA256 hash of the request body in a `payload` tag as hex (`["payload", "<sha256-hex>"]`), servers MAY check this to validate that the requested payload is authorized.

If one of the checks was to fail the server SHOULD respond with a 401 Unauthorized response code.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this should be 403 if the Authorization header was actually sent.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to kindly request that we avoid introducing a breaking change at this advanced stage, especially since the implementations are already being used in real-world settings.

NAV-3 is implemented and will be using the original version. So, by introducing this change, we may unintentionally exclude Nostr users from personal storage on the web. This could put an increased load on our relays, which might not be the best outcome for all involved.

Let's not forget our guiding principle stated in the NIPs which urges us to be mindful of avoiding breaking changes. Such changes not only have the potential to disrupt our current operations but can also discourage developers, perhaps even to the point where they might consider moving on.

More importantly, we have to remember the reputation of our project is at stake here. Breaking changes, especially ones that may not have clear and significant benefits, can potentially give the entire initiative a less than positive image.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP 401 Unauthorized: "I don't know who you are, please tell me before I can proceed"

HTTP 403 Forbidden: "I know who you are, but you still can't access this"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what the constraints related to your project are, but if this is the correct usage of 401 that's fine, I'm not 100% clear on the nuances.

@rabble
Copy link
Copy Markdown
Collaborator

rabble commented Jun 12, 2023

Doesn't https://ucan.xyz/ basically do serverless JWT for authorization like we're looking at for this?

@v0l v0l merged commit c8c2ab6 into nostr-protocol:master Jun 17, 2023
@v0l v0l deleted the nip98 branch June 17, 2023 18:21
@alexgleason
Copy link
Copy Markdown
Member

I implemented NIP-98 auth in Ditto: https://gitlab.com/soapbox-pub/ditto/-/blob/develop/src/middleware/auth98.ts

So you can call Mastodon API endpoints like GET https://ditto.pub/api/v1/accounts/verify_credentials with NIP-98 auth and it'll recognize you and return your Nostr account in Mastodon API format.

One idea which occurred to me... is that NIP-98 + proof of work is an epic combination for deterring spam and DDOS attacks. Nothing stops me from adding a NIP-13 nonce tag to auth events and then validating POW on the server.

You could use this during registration especially.

However, POW with NIP-07 is a bit awkward.

@Dolu89
Copy link
Copy Markdown

Dolu89 commented Aug 4, 2023

I implemented NIP-98 auth in a web component https://github.com/Dolu89/nostr-one
You can put this button on your website and it will call your login API. It's a web component. It's usable with any front-end framework and also on pure HTML/JS pages.

Then you can use NIP-98 from nostr-tools that I implemented too, in your backend to validate the event. https://github.com/nbd-wtf/nostr-tools/blob/3368e8c00e728ff9b4981d58f8f7e546caa1d0f1/nip98.ts#L63C23-L63C36
Documentation is probably not perfect. Don't hesitate if you don't understand something

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.