My understanding is that client impersonation cannot be prevented for Native Desktop Apps. If all standard controls: State, PKCE, Redirect_URI confirmation etc are in place, to prevent auth_code leakage or injection. Then the only way an attacker could reasonably compromise a flow is if they are capable of manipulating the initial request. Specifically by PKCE downgrade attack or challenge_response substitution.

This would allow the attacker to intercept the response, and exchange the auth_code for and id_token. They would then be able to impersonate the user associated with the id_token to an external resource (backend server).

This would require a compromised app that is capable of interfering with the initial request (malicious browser app), or a malicious native app that impersonates the valid app outright.

To me this is no different than if a malicious app is able to record key strokes and is then used to steal credentials on a web page. The security concerns appear to be about the same, in that it requires a device to be compromised in a specific indefensible way.

Question: Can a validly signed id_token from a public native desktop app be considered a form of authentication equivalent to a standard username/password sign-in?

1 Answer 1


An id_token is not intended to be passed to Resource Server (RS) like an API. Use the access_token for this.

If you use an access_token to authenticate at the resource server: Yes, the authentication is as good as username/password. Even better: You don't need to store the user's credentials in the native application. Revoking tokens is always easier than forcing a user to immediately change his credentials...

The id_token is primarily intended for the Relying Party (RP) – e.g. a native application – to verify the user's identity. This is why the aud claim of the id_token must contain the client_id.

REQUIRED. Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. It MAY also contain identifiers for other audiences. In the general case, the aud value is an array of case sensitive strings. In the common special case when there is one audience, the aud value MAY be a single case sensitive string.

(Excerpt from OIDC Core, Section 2)

In contrast, the access_token is intended for the resource server and should therefore contain the resource in its aud claim (if the access_token is a JWT, which it usually is these days for practical reasons).

If the request includes a "resource" parameter (as defined in [RFC8707]), the resulting JWT access token "aud" claim SHOULD have the same value as the "resource" parameter in the request.


If the request does not include a "resource" parameter, the authorization server MUST use a default resource indicator in the "aud" claim. If a "scope" parameter is present in the request, the authorization server SHOULD use it to infer the value of the default resource indicator to be used in the "aud" claim. The mechanism through which scopes are associated with default resource indicator values is outside the scope of this specification. [...]

(Excerpt from RFC 9068, Section 3)

  • My scenario is that I have a desktop application that completes the OIDC flow and then passes then authentication token to a server I control, in this case the token is granted by an IDP, but the token is not intended to access protected resources controlled by the IDP. My server has no ability that would enable it to determine the identity of the owner of a resource token so the id_token must be passed as it contains this information and can be validated. The id_token is consumed and invalidated by my API server after a single exchange. My API server trust the token holder is the owner. Commented Jan 4, 2022 at 18:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .