OIDC Implicit flow - redirect uri length - identityserver4

I'm using OIDC with implicit code flow with response type "id_token token". Everything works great but noticed that callback url with access token, id_token, scope and session_state + domain name already contains 2033 characters. Project that I'm working on needs to support IE 10 and as far as I know there is a limit URL 2048 characters. I'm little afraid that length of callback url is apporaching this limit dangerously.
What is suggested approach with cases like that? Could I change response type to "token" and then request user information from user info endpoint? Or maybe should I do something to reduce size of callback url, try to reduce information in access_token and id_token? Third option seems to be reference token but I'm little afraid about overhead with one extra call to STS.
In project I use oidc-client-js and IdentityServer4.
Thanks

Try to keep the token as small as possible. IOW less claims.
IdentityServer removes all additional claims from the identity token by default in scenarios where an access token is available (unless you override this behavior).
Reference tokens are another way of dealing with that as you said. By enabling caching in the API middleware you can keep the overhead small.
IE is the plague.

Similar issue here but with Electron app. Electron app needs to call protected API. API needs to know identity of calling user. I tried changing response type from "id_token token" to "token" but IdentityServer auth attempt now results in :
UI:
Sorry, there was an error : invalid_scope
Debug Output:
Requests for token response type only must include resource scopes, but no identity scopes
Javascript config (borrowed from Dom's great Javascript sample client):
var config = {
authority: "http://localhost:5000",
client_id: "js",
redirect_uri: "http://localhost:5003/callback.html",
response_type: "token",
scope:"openid profile TestApi",
post_logout_redirect_uri : "http://localhost:5003/index.html",
};

Related

Invalid access token when using Auth0

I am making use of the Auth0 service for my user authentication, but I have been having issues whereby the client id keeps returning an invalid user token.
The API accepts access tokens normally and verifies it on the back-end of the application built using NodeJS but at the front-end using ReactJS and Next.JS, I don't get access to a valid access token.
It returns something like this:
eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYtMnp0eGs5ODkudXMuYXV0aDAuY29tLyJ9..rMSEQS4g-2NcYvqU.zmMlNypJoKyO-wwLcxJgnsvcUHrcTH5c7jnNskyvxldZn56Tc_YX1T2vUQpWWNAWTyItAkUJxM58iy-kj29hY3Bz-Y1Q0Vccu8RdEip8Hc6p9f6-pR6bFKwVlLNkhj5oovFSDTv_-WPcYT40E5fTWRxaV4sNnE3ml16Bcu_CtFECmxAuJZWQ83dxWXlgudWXT7dhNMTGEyL2hIhWHlwO-dWkjIGI1wJmEa8v5pd0atawYsJlzukUcfc54alugCjIVEd1_QnGFWseKY05Ezl5VrBZJuEBnS8Qi6lMRreVPZkat64j_5jvEsvC5F5jMO9Qi2c.ezk5VSWPKZYdhBKkUhWP1Q
Also, I tried switching to ID token because that is valid but the JWT validator always returns 'Invalid_user'.
Attached below are some visual representations of the issue faced.
You can try using the ID token with:
const jwtA = require("express-jwt");
var jwtCheck = jwtA({
secret: process.env.AUTH0_SECRET,
audience: process.env.AUTH0_CLIENT_ID,
algorithms: ["RS256"]
});
or confirm in your frontend application that all settings are correct
This looks like an opaque access token (see https://community.auth0.com/t/why-is-my-access-token-not-a-jwt-opaque-token/31028).
Auth0 uses these kinds of access tokens if you don't set a "audience" URL parameter in your /authorize API call (https://auth0.com/docs/api/authentication#database-ad-ldap-passive-). You can find the audience string in the Auth0 admin interface in the section "Applications -> APIs".
If you are using the Auth0 Next.js SDK, you can e.g. set the default audience via the "AUTH0_AUDIENCE" environment variable (see https://auth0.github.io/nextjs-auth0/modules/config.html#configuration-properties).

MSAL - No Tokens Available when Using IneractionType.Redirect

In our application, we authenticate users using AAD, but we authorize users using our own User and Role tables in our local SQL database.
With the old ADAL library, we were able to return users to our callback url, then from there we would grab the JWT token from the ADAL service, and send that token to our server. The server would then validate the token, decode it and grab the email address. We then used our SQL tables to return another JWT that contained the user's identity and all of their roles.
With MSAL, this still works if you use InteractionType.Popup. The response Observable from the loginPopup() method carries the AuthentiationResult, which has an idToken property and an accessToken property. You can easily grab the one you need and you're off to the races.
However, with InteractionType.Redirect we don't get the AuthenticationResult.
I have injected the msalService instance into the our callbackURL's component (called AuthCallbackComponent). I looked everywhere within the msalService for the tokens, but couldn't find them. I even looked in sessionStorage, where I've configured MSAL to cache the token. They are actually in there (under a couple of really funky keys), but not until later. Whether I use ngOnInit, ngAfterViewInit or ngAftercontentInit, the tokens are not there yet. It does work if I set a timeout of 1-2 seconds, but...no. You can never really rely on timeout delays being long enough for all of your users all the time.
We desire to use the Redirect workflow rather than the popup workflow, so it really would be ideal if we can just get the idToken from the MSAL instance.
I found this post here: Retrieve token using msal, which offers some possible solutions, but the suggestions aren't helpful. It talks about a custom MSAL Interceptor, but that seems wrong. That's typically the HTTP interceptor that adds your token to the headers of your service calls. It also says you can subscribe to the callback and "do something with the returned token", but assuming they mean the callback of the msalService.loginRedirect() method, well that is just wrong. It doesn't return anything at all.
Remember, that in the old ADAL library, this worked. Also it still works with InteractionType.Popup (which we can't use). I expect those tokens must be in the MSAL instance somewhere, or else there's a method we can override, a callback we can provide, etc.
Thanks for reading this longer post.
Buried deep within the 10K pages of Microsoft documntation on MSAL, I found this event reference:
https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/v2-docs/events.md#the-inprogress-observable
So I used their example code to come up with my solution, which was to inject the msalBroadcastService into my AuthCallbackComponent. There I subscribe to its msalSubject$, and when a LOGIN_SUCCESS event happens, I can get the accessToken and idToken from the event's payload. Here is some code:
ngOnInit(): void {
this.msalBroadcastService.msalSubject$.pipe(filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS)).subscribe(msg => {
const idToken = (msg.payload as any).idToken;
// now I can call my service method, passing in the idToken
}

Adding bearer token to swagger requests using swagger-client

I'm trying to add a bearer JWT token to a swagger request upon login of an account but I can't seem to get it working. The documentation leaves a lot to be desired.
const SWAGGER_CLIENT = SwaggerClient(".../api.yml");
const carsResponse = await SWAGGER_CLIENT.client.execute({ operationId: "getCars" }); // I need { Authorizations: Bearer ${token}} here
If it's not possible to add it there then I can always create the client above with the token upon a successful login.
I think the issue is the syntax more than anything. There is virtually no documentation on how to use the .execute() method which is very frustrating. FWIW; I'm using the execute method and passing in tag names to make it more reusable than using the generated functions e.g., getCars(), addCar() etc. I don't know if this is the "right" way to use Swagger but it makes sense to me.
Is is possible to add it globally so I needn't include it in every request? The token will need to be added upon a successful login. It's a CRA application using Redux.
If somebody could explain, or provide a small example of adding the authorization bearer token to the request above that be fantastic and greatly appreciated.
Thanks all.
We will be renaming Try It Out Executor to HTTP client for OAS operations. Thanks for your input!

Why does my Auth0 id_token not contain any information about the user?

I started from this React sample application from Auth0 and login through Auth0 works fine but does not give me the expected token.
After login the browser localStorage contains an id_token and a profile object. When I decode the id_token I see that the payload contains something like this:
{
"iss": "https://mycompany.eu.auth0.com/",
"sub": "auth0|5821bc27f92ca3261c628a26",
"aud": "2A8cgDBm86kLCtCNtUMcKPL2G3oqjIdE",
"exp": 1478755859,
"iat": 1478719859
}
The profile contains email and lots of other good stuff from the user profile as registered in Auth0.
I need to parse on the token to my API server and therefore I need the attributes from the profile-object to be part of the token. How can I make the id_token contain all these attributes, so that I can parse it in my API-service and store it the first time the user logs in?
As I see it, I cannot use the profile-object found in the browser localStorage as it needs to be signed by Auth0 in order for my API server to trust the information.
I'm also aware that I can use the id_token to make a request from my API server directly to Auth0 to get this additional information, but I just think it would be simpler and more efficient if the information was carried by the token.
Those are the claims included by default in a id_token; it's possible to request other claims to be included by passing a scope parameter with the appropriate value.
See Scopes - Requesting specific claims, for a reference on what you can pass in the scope parameter in order to influence the contents of the id_token.
To add onto João Angelo's answer, you can't request the entire "App_Metadata" object in scope. If there are app specific fields e.g. lang or favorite color, these have to be called out specifically.
Example App MetaData
Example call
https://example.auth0.com/authorize
?response_type=token
&client_id=YOUR_CLIENT_ID
&redirect_uri=http://jwt.io&connection=google-oauth2
&scope=openid+lang+favoriteColor
There may be additional caveats to the scope parameter, it would be good to ask Auth0 as you run into issues

How to protect my api call from CSRF attack

I am working on angular js app,and tried to make a simple login page and tried to request my server API for authenticate my login call.Here what and how i planned to do.
Note: I am assuming that server is responsible for validating my token and request.
Provide username password to server via API call.
On getting authenticated the server will generate a token for my App(through which i made a call).
I stored this in my browser's COOKIE.
This Cookie (auth token) will be further used by app to to make each and every HTTP call to API.
Now this approach is working fine for me,but I believe it is openly available for CSRF attack.
In order to avoid the CSRF attack from my browser,i provide APP id or (version id) to my code which also travel with cookie to the API for http call.
The idea behind using this version id or App id,is this can be treated as a signature of my code,ie request is coming from the signed (verified) app who has alloted token=cookie value.
i just want to know how better my approach is and how much secure it is for my basic app point of view and for my major (wide project) app.
Here i am trying to show via a rough diagram
apologies for this tiny view and bad handwriting of the diagram.
Backend frameworks like Laravel have this pretty built in: csrf-protection.
You can pass the token to Angular by using angular's constant function: $provide#constant.
So after you initialize your app you could say: angular.module('myApp').constant('<?php echo csrf_token(); ?>'); and Laravel would do the rest. If you would want to implement a technique like this yourself, you should look into Laravel's source code: https://github.com/laravel/framework/blob/a1dc78820d2dbf207dbdf0f7075f17f7021c4ee8/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php.
Adding App ID + Version ID to each request won't protect your system from a CSRF attack, unless these are in a custom header - and if they are you might as well just use X-Requested-With because any non standard header is protected going cross domain, provided you haven't enabled CORS with an open policy.
The reason that checking App ID + Version if set in the query string or POST data is that the attacker can readily gain this information to add the App ID + Version ID to their cross site requests. Another method that would work for you is the Double Submit Cookies technique. Generate a random 128 bit string using a CSPRNG and then set this as a cookie value (e.g. CSRFCookie). On each request to your API, also pass this value. e.g. in the query string: CSRFCookie=<generated value>. On the server side you simply check that the values match. An attacker does not know the cookie value, therefore they cannot add the same value to the query string.
This method does have some minor vulnerabilities, only really exploitable in a MITM scenario or if you do not control all subdomains. Short answer: Use HTTPS only for all your subdomains and implement HSTS.

Resources