View Issue Details

IDProjectCategoryView StatusLast Update
0010172Talermerchant backendpublic2025-07-10 09:25
Reportersebasjm Assigned ToFlorian Dold  
PrioritynormalSeveritymajorReproducibilityhave not tried
Status feedbackResolutionopen 
Summary0010172: should not be able to create to create tokens with a token
DescriptionThis works, and I can use the token returned to create more tokens (on any scope)

$ curl 'http://merchant.taler.test/private/token' -H 'Authorization: Bearer secret-token:GVP8MZ2R22XGNY1KA9Q72RVMHZZ0E7K35E924ZJQECJTT0TFQ6NG' --data-raw '{"scope":"all","duration":{"d_us":"forever"}}'
{
  "access_token": "secret-token:H6QTCSWAD2458EDG09J3JCH98N63ARM0SCXKG4EM3PMP6W942CP0",
  "token": "secret-token:H6QTCSWAD2458EDG09J3JCH98N63ARM0SCXKG4EM3PMP6W942CP0",
  "scope": "all",
  "refreshable": false,
  "expiration": {
    "t_s": "never"
  }
}

The problem is that this is the normal token used by the merchant SPA. I think we should either have a special scope for tokens to create new tokens (1) or only allow the creation of tokens with Basic, not Bearer (2).

I think (2) is the simplest and safest.

We can also go for (1) for a "spa-session" scope. This allows the full management (like all) but prevents the creation of new tokens if leaked.
TagsNo tags attached.

Activities

schanzen

2025-07-09 18:07

administrator   ~0025469

You should not be able to create a token with a broader scope than the one you present. I also though it had to be refreshable. Need to check the code.

schanzen

2025-07-09 18:09

administrator   ~0025470

What is the "normal token used by the SPA"? Because we do not have a scope for that, so I guess you already have a scope with "all". So your description would not be correct. We can define a special scope for SPAs, if you can provide me with a clear requirement and set of permissions required.

schanzen

2025-07-09 18:11

administrator   ~0025471

(Note: "all" always was and still is defined as "can do anything including refresh")

schanzen

2025-07-09 18:12

administrator   ~0025472

We cannot limit the token endpoint to only Basic, because that is what ":refreshable" is about.

schanzen

2025-07-09 18:12

administrator   ~0025473

Your proposal (1) also does not work, because you can request scope "spa-session:refeshable" and get a token that can be refreshed.

Christian Grothoff

2025-07-09 20:37

manager   ~0025474

The SPA clearly should ask for a non-refreshable token, possibly with a lifetime restriction that the user can configure on login.

When the SPA is used to create *another* token for export, I think it makes sense for the SPA to require the user to re-enter username/password for this.

Maybe this is a pure SPA issue and not something that requires changes in the backend?

sebasjm

2025-07-10 04:23

developer   ~0025479

1) the only way to create a new session should be using username and password (or even 2fa)
2) the refresh mechanism re-create the __same__ token (not a new one, in fact, refreshing should invalidate the previous one)

This way the user can keep control of the number of open sessions for an account.
I have shown a way to overcome this two restriction, having a token I can create a new token without user/password and a token without refresh.

a) do we want to have a scope that allow user of the token to create new tokens? (like the "all" scope) (consider that the user of the token may be a script or third party)

I think this is wrong, I don't see any reason why this would be a good idea and the merchant could potentially find an unreasonable amount of new open sessions.

b) how can we fix this?

I proposed 2 ways:
- only allow the creation of tokens using usr/pwd, the refreshing explained in (2) should care about the rest.
- modify the scope definition to exclude token creation permission or to ask for it if needed (again I don't see why but you sound like you have a reason)

If you insist on having a scope that can create tokens, then we need a scope that have "all - creation_of_tokens" __by definition__ since the SPA backoffice should have access to all API but the UI will ask (and test) user password before creating a new token.


> The SPA clearly should ask for a non-refreshable token, possibly with a lifetime restriction that the user can configure on login.

The spa will always ask for refreshable and max duration, this allows the backend server to impose the expiration (spa always check expiration independently of duration). It needs to be refreshable so the session only ends with the user hitting "log out" (or app close for too long)
Asking for non-refreshable token will make the SPA prompt for "enter the username and password again" before expiration (manually refresh) this is worse UX.

> When the SPA is used to create *another* token for export, I think it makes sense for the SPA to require the user to re-enter username/password for this.

The creation of new token is working as you describe. SPA ask for password (and test it) even if not required right now (that's why I'm creating this issue against backend). Password is always thrown away after used, the SPA never ever saves the password.

> You should not be able to create a token with a broader scope than the one you present

Off course, this is not the case. In the example I have started the issue I'm asking for a token (H6QT) with refreshable:false using the token (GVP8). I succeded to create a new token without user/password (using token GVP8 and also using token H6QT) with a token which is not refreshable which makes refreshable property useless. I can also use H6QT again in the same way.

> What is the "normal token used by the SPA"?

A token with scope "all", since the spa session should have access to all endpoints no other scope make sense.

schanzen

2025-07-10 07:53

administrator   ~0025480

The token with scope all is always refreshable. That is actually a bug: The "refreshable" field is set incorrectly in this special case and the refreshability is not indicated.

You claim (1) is still unsubstantiated and everything hinges on the argument why this is a requirement. Why should this not be possible? See also https://oauth.net/2/refresh-tokens/ on how this is a common pattern.

If you mean that the token refresh should invalidate an old token I agree. That would also be a new requirement an behaviour, but I can see why it makes sense.


Tokens are also not sessions. Maybe that is the case for the SPA but a token is simply a token.

The bigger problem is that we are mixing access tokens from login (session tokens) with third party access tokens. Those are actually thwo different things. Maybe this requires a bigger refactor: Separate login tokens (/private/token) from third party tokens (/private/third_party/token)

I think in general we are using terms here in the wrong way. Like access token, session and refresh.

Christian Grothoff

2025-07-10 09:25

manager   ~0025485

Ok, I'm also not sure that we need this, schanzen's arguments here seem quite reasonable. Shall we "wontfix" it?

Issue History

Date Modified Username Field Change
2025-07-09 16:55 sebasjm New Issue
2025-07-09 17:03 Christian Grothoff Assigned To => schanzen
2025-07-09 17:03 Christian Grothoff Status new => assigned
2025-07-09 18:07 schanzen Note Added: 0025469
2025-07-09 18:09 schanzen Note Added: 0025470
2025-07-09 18:11 schanzen Note Added: 0025471
2025-07-09 18:12 schanzen Note Added: 0025472
2025-07-09 18:12 schanzen Note Added: 0025473
2025-07-09 20:37 Christian Grothoff Note Added: 0025474
2025-07-09 20:37 Christian Grothoff Assigned To schanzen => sebasjm
2025-07-09 20:37 Christian Grothoff Status assigned => feedback
2025-07-10 04:23 sebasjm Note Added: 0025479
2025-07-10 07:53 schanzen Note Added: 0025480
2025-07-10 09:25 Christian Grothoff Note Added: 0025485
2025-07-10 09:25 Christian Grothoff Assigned To sebasjm => Florian Dold