WebAPI + Angular4 using IdentityServer4 CORS error - asp.net-web-api

I have a ASP.Net core 1.X application which is setup to use IdentityServer4 with OpenIdConnect for its Authorization.
when I run the service use the browser to go to http://localhost:xxx/api/mycontroller/myresource this correctly redirects me to the identity server for authorization and then returns value.
now when I add a Angular4 files and launch it, it shows the pages as expected, but when the request is made to the http://localhost:xxx/api/mycontroller/myresource from the angularjs I get a CORS error on my browser console.
XMLHttpRequest cannot load http://localhost:5000/connect/authorize?client_id=system.health.check&redirect_uri=http%3A%2F%2Flocalhost%3A64886%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20profile%20roles%20hierarchy%20healthcheck&response_mode=form_post&nonce=636396863541493382.OTI5NmUxOTYtYzE4Mi00MTY3LTgwYTYtNjlhYzhkNDQxYTY3MTYxNzI2MDUtOWM1Yy00MGExLWE2NTEtNmZjZmRjZmNjMmYz&state=CfDJ8HLk2yX8N6hEj4-UtnTRPL4rvxklhhFhg_Yc-8iFJwSP06FoI_9lUwaFJacx2xU81KDenMUSbsVAjF5QowMT_xRL2Z9mWyxFRykvBASUGB3mHk0RjaSCJzjYXtAYTbkbDF0wLzwALBTcaJ2tgwOwuG_vLWr2dAeiLyyqTiSVZqFziwssoMM_a9PXNAobGPHwl125pMihgXZxoylghIa0N_oS_4sswGCAr_kzW7cc9EMHFmApJTy7Yv29wUB4Tp2ddorOBKxt2t4-YqunsqHViKtlx-xUo0jFcuh30ZY4LDz90wLlHDvGkk_xYCqfJFBMaveNQAG5crvoPIiOYQcVJzNQMAzvXM7Z326E7pzVFVa-. Redirect from 'http://localhost:5000/connect/authorize?client_id=system.health.check&redirect_uri=http%3A%2F%2Flocalhost%3A64886%2Fsignin-oidc&response_type=code%20id_token&scope=openid%20profile%20roles%20hierarchy%20healthcheck&response_mode=form_post&nonce=636396863541493382.OTI5NmUxOTYtYzE4Mi00MTY3LTgwYTYtNjlhYzhkNDQxYTY3MTYxNzI2MDUtOWM1Yy00MGExLWE2NTEtNmZjZmRjZmNjMmYz&state=CfDJ8HLk2yX8N6hEj4-UtnTRPL4rvxklhhFhg_Yc-8iFJwSP06FoI_9lUwaFJacx2xU81KDenMUSbsVAjF5QowMT_xRL2Z9mWyxFRykvBASUGB3mHk0RjaSCJzjYXtAYTbkbDF0wLzwALBTcaJ2tgwOwuG_vLWr2dAeiLyyqTiSVZqFziwssoMM_a9PXNAobGPHwl125pMihgXZxoylghIa0N_oS_4sswGCAr_kzW7cc9EMHFmApJTy7Yv29wUB4Tp2ddorOBKxt2t4-YqunsqHViKtlx-xUo0jFcuh30ZY4LDz90wLlHDvGkk_xYCqfJFBMaveNQAG5crvoPIiOYQcVJzNQMAzvXM7Z326E7pzVFVa-' to 'http://localhost:5000/account/login?returnUrl=%2Fconnect%2Fauthorize%2Flogin%3Fclient_id%3Dsystem.health.check%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A64886%252Fsignin-oidc%26response_type%3Dcode%2520id_token%26scope%3Dopenid%2520profile%2520roles%2520hierarchy%2520healthcheck%26response_mode%3Dform_post%26nonce%3D636396863541493382.OTI5NmUxOTYtYzE4Mi00MTY3LTgwYTYtNjlhYzhkNDQxYTY3MTYxNzI2MDUtOWM1Yy00MGExLWE2NTEtNmZjZmRjZmNjMmYz%26state%3DCfDJ8HLk2yX8N6hEj4-UtnTRPL4rvxklhhFhg_Yc-8iFJwSP06FoI_9lUwaFJacx2xU81KDenMUSbsVAjF5QowMT_xRL2Z9mWyxFRykvBASUGB3mHk0RjaSCJzjYXtAYTbkbDF0wLzwALBTcaJ2tgwOwuG_vLWr2dAeiLyyqTiSVZqFziwssoMM_a9PXNAobGPHwl125pMihgXZxoylghIa0N_oS_4sswGCAr_kzW7cc9EMHFmApJTy7Yv29wUB4Tp2ddorOBKxt2t4-YqunsqHViKtlx-xUo0jFcuh30ZY4LDz90wLlHDvGkk_xYCqfJFBMaveNQAG5crvoPIiOYQcVJzNQMAzvXM7Z326E7pzVFVa-' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:64886' is therefore not allowed access.
However the logs on the IdentityServer4 shows
BTW http://localhost:5000 is my IdentityServer4 address and http://localhost:64886 is the service serving the Angular files and hosting the WebAPI.
Any ideas what I may be missing here?
UPDATE 1
Not sure if this helps, but my OpenIdConnectOption is setup as below
"OpenIdConnectOptions": {
"AuthenticationScheme": "oidc",
"SignInScheme": "Cookies",
"Authority": "http://localhost:5000",
"RequireHttpsMetadata": false,
"ClientId": "system.health.check",
"ClientSecret": "secret",
"ResponseType": "code id_token",
"GetClaimsFromUserInfoEndpoint": true,
"SaveTokens": true,
"Scope": [ "roles", "hierarchy", "healthcheck" ]
},
UPDATE 2
If I put in the [Authorize] attribute on my HomeController things work as expected as its redirecting me to the login page even before the Angular files are shown. So does it mean that I cannot have the WebAPI controller protected unless the MVC is first Authorized? Also why do I get a CORS error in this case.
Regards
Kiran

I ran into the same issue and ended up using the [Authorize] on HomeController, but you can do it within Angular as well
if you want to authorize within the Angular application you have to switch the client Grant Type to "Implicit" and do the oidc with an javascript library. You also have to change the responseType from "code id_token" to only "id_token" because in an angular app you cannot open a private backchannel for the code.
OIDC Javascript client:
https://github.com/IdentityModel/oidc-client-js
Here is an article which explains your approach:
https://damienbod.com/2016/10/01/identityserver4-webapi-and-angular2-in-a-single-asp-net-core-project/

Related

Vue3 with Sanctum - Subdomains get unauthenticated even user login successfully

I'm having an application with 5 different sub-applications where they use multiple sub-domains under one main domain with vue2. Everything working with vue2 implementations. And I'm trying to implement auth UIs (its a separate vue3 project) with the below technologies
Vue 3.2
2.Vue router 4.1
3.Vite 3.0
4.Pinia 2.0
So my applications are like below with vue2
Auth app (localhost:3000)
Profile app (localhost:3001)
Dashboard app (localhost:3002)
At the moment I have implemented all the functionalities related to Auth app with vue3. But I'm having an issue with that. So initial applications will work as follow.
User gets authenticated via auth app and then redirect to Profile app
If the user clicks on the dashboard app link it will redirect the user back to auth app with redirect_uri so that when it redirects to auth app will check auth status and if the user is authenticated then the user will be redirected to the redirect_uri which comes with router query.
At the moment this is working with vue2. But it's not working with vue3.
How does it work with Vue3.
Send a get request to /sanctum/csrf-cookie and then send a post request with email and password.
After successful login redirect the user to the Profile app. (But app says unauthenticated for all requests and it will redirect back to auth app - 3000)
I use the below configurations
import axios from "axios";
const instance = axios.create({
withCredentials: true,
baseURL: import.meta.env.VITE_APP_API_URL,
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
If I use Vue 2 auth app then everything works as required.
IF I REFRESH THE PAGE AFTER LOGIN WITHOUT REDIRECTING THE USER TO PROFILE IT WILL SUCCESSFULLY GET THE CURRENT USER. BUT ASS SOON AS I REDIRECT USER TO PROFILE THEN IT SAYS Unauthenticated AND REDIRECT TO LOGIN. AT THIS MOMENT USER IS UNAUTHENTICATED AND NEEDS TO RE-LOGIN.
I have referred so many answers at Laracast and StackOverflow. But wasn't able to find the exact issue. Really appreciate any help on this one.
Thanks

Okta api invalid request

I'm trying to fit the Okta Asp.NET Core Mvc example (https://github.com/oktadeveloper/okta-aspnetcore-mvc-example) into my React Asp.Net Core app. (The reason I'm not using Okta's React example is that it uses Babel and my VS2017 React project uses Typescript.) The Mvc example runs fine against my Okta account, and my React app compiles and runs w the Okta SDK and other code copied from the Mvc example, but I can't get it to authenticate.
Okta returns an http 400: Identity Provider: unknown, Error Code: invalid request, Description: the 'redirect_uri' parameter must be an absolute Uri that is whitelisted in the client app settings.
All I've done is add [authorize] attribs to my controller and a button that requests account/login. Both actions return the same error. I do have the app Url in my Okta app settings.
This, most likely does not have anything to do with React/asp.net but the OIDC flow. If we strip down the SDK, your call to get the jwt token will look something like this: {{url}}/oauth2/v1/authorize?idp=0oae59ifqdtRaTT4G0h7&client_id={{client_id}}&response_type=id_token&response_mode=fragment&scope=openid&redirect_uri=https://www.bing.com
note the redirect_uri above should be the listed in your application setting. To do that: go to Okta's admin dashboard > application >application > choose the application that you used the id of above, and add the above URL to "Login redirect URIs" in the general tab. If that is correct make sure there is no space in the above request.

SSO In an old ASP.NET Web Forms website

Context:
The company I'm working for would like to achieve Single-Sign-On capabilities with a third party that uses the authorization code grant. Our product right now is built in .NET Framework 4.0 using Forms Authentication in a ASP.NET Web Forms application.
Question:
Is there a way to achieve single sign-on with out the user having to sign in twice (once through forms auth, and another through the identity server)?
To elaborate, is there a way to have the identity server authenticate the user automatically after the user has successfully signed in through forms authentication?
Here's the IdSvr3 webforms client: https://github.com/IdentityServer/IdentityServer3.Samples/tree/master/source/Clients/WebFormsClient
From what I've read, IdentityServer3 clients (which are previous to .NET core) are supposed to work with IdentityServer4 (which has to run on .NET core) and will talk to IdentityServer4 successfully.
So I managed to work around my issue by sending the users credentials on login to the identity server via ajax. I made a webapi controller that authenticates the user and sends back 'set-cookie' response headers for the idsrv auth cookie.
So now I'm signed into the original application, as well as the identity server all without the user having to manually sign in twice.
You just have to deal with a bunch of Cross-Origin-Requests stuff. Have to set "AllowCredentials" when setting up the CORS policy for the application to make the ajax request so that the 'set-cookie' headers actually apply.
$.ajax({
method: 'GET',
url: 'https://localhost:44304/api/login?username=testing&password=testing',
crossDomain: true,
xhrFields: {
withCredentials: true
}
})
The api/login endpoint is defined in a Controller that just calls the HttpContext.SignInAsync() extension method.

Identityserver3: Token validation requests not visible in Fiddler

In fiddler composer, I execute a call to a local api that is secured by a local identityserver3.
I added the token, and I configured the middleware to validate the token on the server. Tt works fine, in Idenityserver3 log file I see a succesful token validation logmessage for the configured scope.
I assume that, with htis config, each time the api is called, the Idsrv3 middleware calls the token validation endpoint under the hood.
My issue is that fiddler does not show this middleware request, just the call to the api itself. Is this due to fiddler settings or is there another reason this request is invisible to fiddler?
Is there a way to display it?
Thanks
It could be that .NET is not routing the localhost traffic to fiddler proxy. For workaround check this.
http://docs.telerik.com/fiddler/observe-traffic/troubleshooting/notraffictolocalhost
Also, check if you have configured validation mode properly. According to documentation https://identityserver.github.io/Documentation/docsv2/endpoints/identityTokenValidation.html validation endpoint is useful if you have no access to crypto libraries locally.
Valid validation modes are
ValidationMode.Both - Use local validation for JWTs and the validation endpoint for reference tokens
ValidationMode.Local - Use local validation oly (only suitable for JWT tokens)
ValidationMode.ValidationEndpoint - Use the validation endpoint only (works for both JWT and reference tokens)
You can set the validation mode in IdentityServerAuthenticationOptions
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44333/core",
//RequiredScopes = new[] { "write" },
// client credentials for the introspection endpoint
ClientId = "write",
ClientSecret = "secret",
ValidationMode = ValidationMode.Local
});

Understanding the VS2013 MVC5 SPA Template WebAPI Security Features

I am trying to understand the security features of the VS2013 MVC5 SPA Template WebAPI.
In Startup.Auth.cs there is this -
TokenEndpointPath = new PathString("/Token")
and this -
AuthorizeEndpointPath = new PathString("/Account/Authorize")
In my understanding, the AuthorizeEndPointPath is for when your acting as a 3rd Party OAuth authorization server.
However how it is used in the template, the flow seems to be
Login via Forms Authentication
Redirect to a secure page
Javascript checks for a bearer token in the local storage, it doesn't exist, so it redirects to this Authorize endpoint.
window.location = "/Account/Authorize?client_id=web&response_type=token&state=" + encodeURIComponent(window.location.hash);
Logs into app with OAuth security, returns token, which will be passed on subsequent API requests.
The /Token endpoint never seems to be used. A prior version of this templated did an ajax post to /Token to login. I have a similar situation where the website is secured via Forms authentication/cookies but the WebApi is secured by Bearer token.
Is the Authorize endpoint being used correctly in this SPA template - is this the correct pattern to follow? It seems like the appropriate way to authenticate for bearer token security "internally" for the app would be a "client credentials grant" though not sure how to generate the "secret".

Resources