Configure Identity Server 4 With Ionic 2 - javascript

I'm trying to configure Identity Server to work with Ionic 2. I'm a bit confused on how to configure the Redirect urls. For when I'm testing in the browser.
I'm in the process of updating and integrating an OIDC Cordova component.
The old component git hub is here:
https://github.com/markphillips100/oidc-cordova-demo
I've created a typescript provider and registered it with my app.module.ts
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import { Component } from '#angular/core';
import * as Oidc from "oidc-client";
import { Events } from 'ionic-angular';
import { environment } from "../rules/environments/environment";
export class UserInfo {
user: Oidc.User = null;
isAuthenticated: boolean = false;
}
#Injectable()
export class OidcClientProvider {
USERINFO_CHANGED_EVENT_NAME: string = ""
userManager: Oidc.UserManager;
settings: Oidc.UserManagerSettings;
userInfo: UserInfo = new UserInfo();
constructor(public events:Events) {
this.settings = {
//authority: "https://localhost:6666",
authority: environment.identityServerUrl,
client_id: environment.clientAuthorityId,
//This doesn't work
post_logout_redirect_uri: "http://localhost/oidc",
redirect_uri: "http://localhost/oidc",
response_type: "id_token token",
scope: "openid profile",
automaticSilentRenew: true,
filterProtocolClaims: true,
loadUserInfo: true,
//popupNavigator: new Oidc.CordovaPopupNavigator(),
//iframeNavigator: new Oidc.CordovaIFrameNavigator(),
}
this.initialize();
}
userInfoChanged(callback: Function) {
this.events.subscribe(this.USERINFO_CHANGED_EVENT_NAME, callback);
}
signinPopup(args?): Promise<Oidc.User> {
return this.userManager.signinPopup(args);
}
signoutPopup(args?) {
return this.userManager.signoutPopup(args);
}
protected initialize() {
if (this.settings == null) {
throw Error('OidcClientProvider required UserMangerSettings for initialization')
}
this.userManager = new Oidc.UserManager(this.settings);
this.registerEvents();
}
protected notifyUserInfoChangedEvent() {
this.events.publish(this.USERINFO_CHANGED_EVENT_NAME);
}
protected clearUser() {
this.userInfo.user = null;
this.userInfo.isAuthenticated = false;
this.notifyUserInfoChangedEvent();
}
protected addUser(user: Oidc.User) {
this.userInfo.user = user;
this.userInfo.isAuthenticated = true;
this.notifyUserInfoChangedEvent();
}
protected registerEvents() {
this.userManager.events.addUserLoaded(u => {
this.addUser(u);
});
this.userManager.events.addUserUnloaded(() => {
this.clearUser();
});
this.userManager.events.addAccessTokenExpired(() => {
this.clearUser();
});
this.userManager.events.addSilentRenewError(() => {
this.clearUser();
});
}
}
I'm trying to understand how I would configure the redirect urls so I can authenticate normally in the browser. Normally you would configure a redirect
url to take your process the token and claims after login.
this.settings = {
authority: environment.identityServerUrl,
client_id: environment.clientAuthorityId,
post_logout_redirect_uri: "http://localhost:8100/oidc",
redirect_uri: "http://localhost:8100/oidc",
response_type: "id_token token",
scope: "openid profile AstootApi",
automaticSilentRenew: true,
filterProtocolClaims: true,
loadUserInfo: true,
//popupNavigator: new Oidc.CordovaPopupNavigator(),
//iframeNavigator: new Oidc.CordovaIFrameNavigator(),
}
Ionic 2 doesn't use urls for routing, Supposing I have a component AuthenticationPage which handles storing the authentication token.
How can I configured a redirect url so it navigates to the authentication page, so I can test this in the browser?

TL;DR
I had to do a few things to get this working.
I didn't realize at first but My Redirect Urls had to be matching for what my client has stored in identity server.
new Client
{
ClientId = "myApp",
ClientName = "app client",
AccessTokenType = AccessTokenType.Jwt,
RedirectUris = { "http://localhost:8166/" },
PostLogoutRedirectUris = { "http://localhost:8166/" },
AllowedCorsOrigins = { "http://localhost:8166" },
//...
}
So the OIDC client in Typescript needed to be updated too.
this.settings = {
authority: environment.identityServerUrl,
client_id: environment.clientAuthorityId,
post_logout_redirect_uri: "http://localhost:8166/",
redirect_uri: "http://localhost:8166/",
response_type: "id_token token",
}
Also since I didn't feel like setting up routing in Ionic I needed to figure out a way to a url to communicate with Ionic (For Browser testing purpose, normal commucation will be done through cordova).
So I pointed the redirct url to be the url ionic is hosting my application and on app.Component.ts in the Constructor I added code to try to get my authentication token.
constructor(
public platform: Platform,
public menu: MenuController,
public oidcClient: OidcClientProvider
)
{
//Hack: since Ionic only has 1 default address, attempt to verify if this is a call back before calling
this.authManager.verifyLoginCallback().then((isSuccessful) => {
if (!isSuccessful) {
this.authManager.IsLoggedIn().then((isLoggedIn) => {
if (isLoggedIn) {
return;
}
this.nav.setRoot(LoginComponent)
});
}
});
}
Edit Verify login call back should just the oidc client call back which will read the token from the get params
verifyLoginCallback(): Promise<boolean> {
return this.oidcClient.userManager.signinPopupCallback()
.then(user => {
return this.loginSuccess(user).
then(() => true,
() => false);
}, err => { console.log(err); return false; });
}
NOTE the Login component is just a modal which represents login landing page, which just uses a login button to initialize the popup. You can hook this into any user driven event to trigger the login, but you must use a user driven event if you want to support the web without triggering a popup blocker
<ion-footer no-shadow>
<ion-toolbar no-shadow position="bottom">
<button ion-button block (click)="login()">Login</button>
</ion-toolbar>
</ion-footer>
login(): Promise<any> {
return this.oidcClient.signinPopup().then((user) => {
this.events.publish(environment.events.loginSuccess);
}).catch((e) => { console.log(e); });
}
I'm sure there is a better do the redirect to a different route, This is just a quick and dirty hack

Related

AWS-Amplify, How do I redirect to another URL after sign-in in angular?

I'm using the latest AWS-Amplify's authentication component. It can logged in successfully but after login I need to sent the route to another url which I can't able to achieve, it keeping the same url after logged in. BUT I need to set a custom url where it automatically redirect if a user login successfully.
Note : I'm not using aws-amplify-angular package I'm using these packages,
"#aws-amplify/ui-angular": "^2.4.4",
"aws-amplify": "^4.3.21",
Also I checked this import {AuthenticatorService} from '#aws-amplify/ui-angular'; service but here I didn't find any response with observable type, I think that's why I don't get any event or something instantly after user login successfully. I need to route imminently after a successful login. So I need an event so that I can do that .
My main.ts :
import { Amplify } from 'aws-amplify'
import awsmobile from './aws-exports'
Amplify.configure(awsmobile)
auth.component.html : [ there is no code in ts ]
<amplify-authenticator [signUpAttributes]="['email']"></amplify-authenticator>
& the routes setup like this,
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
canActivate: [AuthGuard]
},
{
path: 'auth',
component: AuthComponent
},
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
}
];
I didn't get any good solution with using this packages. Please help with this issue or am I missed something in my configuration .
I didn't want to use aws-amplify-angular package but I need to because there is no good solution out there, without this package I tried to use angular hooks because when change detection runs I can get authenticated & unauthenticated states from AuthenticatorService which came from import { AuthenticatorService } from '#aws-amplify/ui-angular'; but using hooks (AfterContentChecked, AfterViewChecked) it works sometimes,sometimes not & sometimes occurred errors.
[ I did't use both hooks at a time, I tried separately]
So, Finally I need to install aws-amplify-angular for using the AmplifyService's & then I do this changes bellow,
constructor(private router: Router, private amplifyService: AmplifyService) { }
ngOnInit() {
this.amplifyService.authStateChange$.subscribe(({state, user}) => {
if (state === 'signedIn') {
this.router.navigate(['/home'])
}
})
}
Don't forget to add AmplifyService to put in providers array in app.module.ts.
In the AuthenticatorService import of the latest version of #aws-amplify/ui-angular, you can subscribe and listen for authStatus which is authenticated, deauthenticated and configured, if you listen from ngOnInit or from the constructor you can wait for the necessary status to do redirection.
It also works for the signOut
constructor(public amplifyService: AuthenticatorService, public router: Router) {
this.amplifyService = amplifyService;
amplifyService.subscribe((data: any) => {
if (data.authStatus === "authenticated") {
this.router.navigate(['/home']);
};
})
}
ngOnInit(): void {
}
to make signOut you just have to use this function in your navbar
logOut() {
this.amplifyService.signOut()
this.router.navigate(['/login']);
}
This way you can maintain the latest version of aws-amplify packages and not get errors or failures from compiling outdated packages or packages that conflict with other aws packages.
import { Hub } from 'aws-amplify';
ngOnInit() {
// Used for listening to login events
Hub.listen('auth', ({ payload: { event, data } }) => {
if (event === 'signIn') {
const { signInUserSession = {} } = data;
const { accessToken = {} } = signInUserSession;
const { jwtToken, payload = {} } = accessToken;
const { 'cognito:groups': roles, username, exp } = payload;
localStorage.setItem('accessToken', jwtToken);
const payloadToSave = {
Role: roles[0],
Username: username,
exp,
};
localStorage.setItem('payload', JSON.stringify(payloadToSave));
this.zone.run(() => this.router.navigate(['/dashboard']));
} else {
console.log('Hide loader');
}
});
//currentAuthenticatedUser: when user comes to login page again
Auth.currentAuthenticatedUser()
.then(() => {
this.router.navigate(['/dashboard'], { replaceUrl: true });
})
.catch(err => {
console.log(err);
});
}

CORS Problem - Protecting ReactJS Frontend and JAX-RS Backend with Keycloak

I am a Junior Software Developer from Germany and I am currently trying to setup some Webservices from a Jax-RS Rest API (deployed on a Wildfly Server) that are protected by „Keycloak“ and accessible through a simple react app.
I have done all the exact steps from this article: https://medium.com/devops-dudes/secure-front-end-react-js-and-back-end-node-js-express-rest-api-with-keycloak-daf159f0a94e.
The only differences are the the following:
I have three services: „Level Zero“, „Level One“ and „Level Two“.
Every Service simply returns a string (Example: "This is the Service Level One")
I have two Roles defined in Keycloak: „Level One User“ and „Level Two User“
The Level Two User shall be auhtorized to access all the services
The Level One User shall only be authorized to access the services Level One and Level Zero
every other User shall only be able to access the service Level Zero
In my React App I have three Buttons that shall access a service via the framework "axios". You click on a Button, and the returned string shall be logged out in the console if you are authorized to do so.
My Problem:
If I run my app, I always get a CORS Error in my Webconsole when I try to access "LevelOne" or "LevelTwo" as an authenticatd Level One or Level Two User. This problem does not exist with the Level Zero service that is not protected by Keycloak.
My (translated) Error:
Cross Origin Request Blocked: Same Origin Policy does not allow Read-Access on the external resource URL_FROM_API_SERVICE - REASON: CORS Header 'Access-Control-Allow-Origin" is missing!
I tried a lot of stuff that I have found online --> I created a CORS-Filter in my Rest API, I tried to put "enable-cors:true" in my keycloak.json, I put something in the "web-origins" field in my Keycloak client configuration. But nothing worked. :(
What am I doing wrong? I really need your help! I am quite new to all of this and would really appreciate some support.
My Keycloak Configuration is the same as shown in the article, except for the different names.
It also did not help to add "enable-cors:true" in the keycloak.json and setting the "web-origin" to the right origin on the Keycloak Admin Console :(
The API and the React App run on HTTP at the moment, while Keycloak runs on HTTPS on another machine with a self signed certificate.
Here is all my Code:
My App.js from the React App:
import './App.css';
import Secured from './components/Secured.js'
import axios from 'axios';
var axiosInstance = axios.create({
baseURL: 'http://MY_BASE_URL/login-restapi/api/'
});
axiosInstance.interceptors.request.use(
config => {
const token = window.accessToken ? window.accessToken : 'dummy_token';
config.headers['Authorization'] = 'Bearer' + token;
return config;
},
error => {
Promise.reject(error)
});
axiosInstance.interceptors.response.use((response) => {
return response
}, function (error) {
return Promise.reject(error);
});
function App() {
return (
<div className="App">
<Secured></Secured>
<button onClick={() => {
axiosInstance.get('/levelZero').then(res => {
console.log(res.data)
})
}
}>LevelZero</button>
<button onClick={() => {
axiosInstance.get('/levelOne').then(res => {
console.log(res.data)
})
}
}>LevelOne</button>
<button onClick={() => {
axiosInstance.get('/levelTwo').then(res => {
console.log(res.data)
})
}
}>LevelTwo</button>
</div>
);
}
export default App;
My Secured.js from the React App:
import React, { Component } from 'react';
import Keycloak from 'keycloak-js';
class Secured extends Component {
constructor(props) {
super(props);
this.state = { keycloak: null, authenticated: false };
}
componentDidMount() {
const keycloak = Keycloak('/keycloak.json');
keycloak.init({ onLoad: 'login-required' }).then(authenticated => {
this.setState({ keycloak: keycloak, authenticated: true})
if (authenticated) {
window.accessToken = keycloak.token;
}
})
}
render(){
if (this.state.keycloak) {
if(this.state.authenticated) return (
<div>
<p>You are now logged in :)</p>
</div>
); else return (<div>Unable to authenticate!</div>)
}
return (
<div>Initializing Keycloak...</div>
);
}
}
export default Secured;
My Keycloak.json from the react app:
{
"realm": "(MY_REALM_NAME)",
"auth-server-url": "MY_AUTHSERVER_URL",
"ssl-required": "none",
"resource": "react-web-app",
"public-client": true,
"verify-token-audience": true,
"use-resource-role-mappings": true,
"confidential-port": 0
}
My Level Zero Service:
#Path("/levelZero")
public class LevelZeroResource {
#GET
#Produces("text/plain")
public String levelZero() {
return "Everybody can access this.";
}
}
My Level One Service:
#Path("/levelOne")
public class LevelOneResource {
#GET
#Produces("text/plain")
public String levelOne() {
return "You need to be at least a Level One User to access this.";
}
}
My Level Two Service:
#Path("/levelTwo")
public class LevelTwoResource {
#GET
#Produces("text/plain")
public String levelTwo() {
return "You need to be a LevelTwo-user to access this.";
}
}
My CORS Filter from the Rest API:
#Provider
public class CORSFilter implements ContainerResponseFilter {
#Override
public void filter(final ContainerRequestContext requestContext,
final ContainerResponseContext cres) throws IOException {
cres.getHeaders().add("Access-Control-Allow-Origin", "http://URL_FROM_REACT_APP");
cres.getHeaders().add("Access-Control-Allow-Headers", "*");
cres.getHeaders().add("Access-Control-Allow-Credentials", "*");
cres.getHeaders().add("Access-Control-Allow-Methods", "*");
cres.getHeaders().add("Access-Control-Max-Age", "1209600");
}
}
My Keycloak.json from the Rest API:
{
"realm": "MY_REALM_NAME",
"bearer-only": true,
"enable-cors": true,
"auth-server-url": "https://MY_AUTH_SERVER_URL",
"ssl-required": "none",
"resource": "login-restapi",
"verify-token-audience": true,
"use-resource-role-mappings": true,
"confidential-port": 0
}
My web.xml from the Rest API:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<module-name>login-restapi</module-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>LevelOneResource</web-resource-name>
<url-pattern>/api/levelOne</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>levelOneRole</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>LevelTwoResource</web-resource-name>
<url-pattern>/api/levelTwo</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>levelTwoRole</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>KEYCLOAK</auth-method>
<realm-name>MY_REALM_NAME</realm-name>
</login-config>
<security-role>
<role-name>levelOneRole</role-name>
</security-role>
<security-role>
<role-name>levelTwoRole</role-name>
</security-role>
</web-app>
You should not need to add a custom filter.
Simply set enable-cors to true (as you did) and make sure that the Web origins are correctly configured within Keycloak. You need to add the origin of your react frontend to the list of Web origins in your client configuration in Keycloak.
Keycloak will then encode these origins as valid origins inside of your access token. The Keycloak adapter in your JAX-RS application will interpret them and return the Access-Control-Allow-Origin header as needed.
I saw you have enabled the cors in your keycloak config file "enable-cors: true" so make sure the web origins fields on the keycloak (as shown by #sventorben) have the backend url too.
Because even if keycloak-js authenticates the user the backend does the authorization which means talks to keycloak too.

Nuxt: Auth + Axios setup

I'm struggling with the configuration of auth + Axios.
I'm currently working on our social login (FB and google). It half works.
First of all, I have my Axios instance configured as a plugin. We do have two instances, one that we use for general API requests and another one that we will use for logged user requests.
plugins/axios.js
export default function({ $axios, redirect, app }) {
$axios.defaults.baseURL = process.env.baseUrl
$axios.defaults.headers = {
Authorization: `Bearer ${process.env.APIKey}`,
Accept: 'application/json',
'Content-Type': 'application/json',
lang: app.i18n.locale
}
$axios.onError(error => {
const code = parseInt(error.response && error.response.status)
if (code === 400) {
redirect('/400')
}
if (code === 404) {
redirect('/404')
}
if (code === 500) {
redirect('/500')
}
})
}
plugins/auth-axios.js
export default function({ $axios }, inject) {
const authAxios = $axios.create()
// authAxios.setToken('123', 'Bearer')
inject('authAxios', authAxios)
}
The first client works perfectly in the whole app.
Now I'm configuring the auth plugin. When I log in through Facebook or google I need to take the response data of the logged user from the social network and send it to my API, expecting a user with the token as the response. This will be the user that I'll set in the auth plugin. Every time I log in with Facebook it appears to work well except when It arrives at the plugin code. $auth.loggedIn is always false.
I've made it work forcing $auth.fetchUser at the beginning of the code but it doesn't work well at all. It shows an Axios error when console.log($auth). This is my auth code:
plugins/auth.js
export default async function({ app: { $auth, $axios } }) {
$auth.fetchUser()
console.log($auth)
if (!$auth.loggedIn) {
return
}
const authStrategy = $auth.strategy.name
if (authStrategy === 'facebook' || authStrategy === 'google') {
if ($auth.user.google_id || $auth.user.fb_id) return
try {
const url = `/client/social`
var postData
if (authStrategy == 'facebook')
postData = {
name: $auth.user.name,
email: $auth.user.email,
fb_id: $auth.user.id,
avatar: $auth.user.picture.data.url,
birthday: $auth.user.birthday
}
else
postData = {
name: $auth.user.given_name,
surname: $auth.user.family_name,
email: $auth.user.email,
google_id: $auth.user.sub,
avatar: $auth.user.picture,
locale: $auth.user.locale
}
const { data } = await $axios.post(url, postData)
$auth.setToken('client', data.access_token)
$auth.setUser(data.client)
} catch (e) {
console.log(e)
}
}
}
The console.log($auth) error:
'$state': {
user: null,
loggedIn: false,
strategy: 'facebook'
},
error: TypeError: Cannot set property 'Authorization' of undefined
at Function.setHeader (server.js:1556:42)
at Oauth2Scheme._setToken (server.js:1014:31)
at Oauth2Scheme.mounted (server.js:1001:12)
at Auth.mounted (server.js:516:42)
at Auth.init (server.js:459:18)
at module.exports../.nuxt/auth/plugin.js._webpack_exports_.default (server.js:939:16)
at createApp (server.js:2432:87)
}
And my auth module config:
import dotenv from 'dotenv'
dotenv.config()
export const auth = {
plugins: [
// {
// src: '~/plugins/axios',
// ssr: true
// },
{
src: '~/plugins/auth-axios',
ssr: true
},
'~/plugins/auth.js'
],
redirect: {
login: '/',
callback: '/callback'
},
strategies: {
local: false,
facebook: {
client_id: '#############',
userinfo_endpoint:
'https://graph.facebook.com/v2.12/me?fields=about,name,picture{url},email,birthday',
scope: ['public_profile', 'email', 'user_birthday']
},
google: {
client_id:
'#####################'
}
}
}
Seems that auth when login is trying to set the Axios token (also when I log out it tries to remove it) but it fails. If I go to the Chrome dev tools and debug it to see which Axios instance is trying to use for that. Every time is the main Axios instance and it's supposed to be accessible there.
Screenshot from DevTools:
Screenshot from DevTools
Does someone know what I'm missing? Can I prevent auth facebook strategy to update any Axios instance? Or, can I specify which Axios instance to update (set / remove token)?
EDIT: Forcing the $auth.fetchUser my auth plugin code does work but with the error mentioned before. When I try to logOut it doesn't work due to the same error when trying to remove the token automatically)
I'm going crazy with this issue for two weeks now.
Thanks so much!

identityserver4 with oidc-client implicit flow redirect not showing login page

I am trying to use the oidc-client with identityserver4 using the implicit flow.
Here is my Client Configuration.
new Client
{
ClientId = "crushingtheweb.ui",
ClientName = "Crushing The Web.UI",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RequireConsent = false,
AllowedCorsOrigins = new[] { "http://localhost:52668" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"ctw"
},
RedirectUris = new List<string> {"http://localhost:52668/callback"},
PostLogoutRedirectUris = new List<string> { "http://localhost:52668/out" }
}
Here is the oidc-client, client configuration and my call to signinRedirect.
import { UserManager, UserManagerSettings, User } from 'oidc-client';
import { inject } from 'aurelia-framework';
#inject(UserManager)
export class AdminChat {
userManager: UserManager;
constructor(userManager) {
this.userManager = userManager;
console.log('oidc', this.userManager);
let config = {
authority: 'http://localhost:65027',
client_id: "crushingtheweb.ui",
redirect_uri: "http://localhost:52668/callback",
response_type: "id_token token",
scope: "openid profile ctw",
post_logout_redirect_uri: "http://localhost:52668/out",
};
var mgr = new UserManager(config);
mgr.signinRedirect();
}// ctor()
}// AdminChat class
The login page is never shown and it immediately redirects to the callback url, so obviously the user is still undefined.
Any Help would be appreciated!

XMLHttpRequest cannot load No 'Access-Control-Allow-Origin' > header is present on the requested resource

I have an angular APP with .net CORE web API, where the first request is against a /token service, however I get this error about CORS, but apparently I already have it enabled, what am I missing?
:8088/#/home:1 XMLHttpRequest cannot load
http://example.com:90/api/token. No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin
'http://example.com:8088' is therefore not allowed access.
public partial class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var corsBuilder = new CorsPolicyBuilder();
corsBuilder.AllowAnyHeader();
corsBuilder.AllowAnyMethod();
corsBuilder.AllowAnyOrigin(); // For anyone access.
//corsBuilder.WithOrigins("http://localhost:56573"); // for a specific url. Don't add a forward slash on the end!
corsBuilder.AllowCredentials();
services.AddCors(options =>
{
options.AddPolicy("SiteCorsPolicy", corsBuilder.Build());
});
// Add framework services.
services.AddMvc()
.AddJsonOptions(a => a.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver()); ;
//using Dependency Injection
services.AddSingleton<IEcommerceRepository, EcommerceRepository>();
//services.AddSingleton<ITodoTerrenoRepository, TodoTerrenoRepository>();
services.AddDbContext<EcommerContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("AuthentConnection")));
services.AddDbContext<TODOTERRENOContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.Configure<IISOptions>(options =>
{
options.AutomaticAuthentication = true;
options.ForwardClientCertificate = true;
options.ForwardWindowsAuthentication = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
ConfigureAuth(app);
app.UseCors("SiteCorsPolicy");
app.UseMvc();
}
}
}
In my angular APP, i have this:
LoggingService.js
angular
.module('common.services')
.factory('loginservice', ['$http', 'appSettings', loginservice]);
function loginservice($http, appSettings) {
this.login = function () {
var resp = $http({
url: appSettings.serverPath + 'token',
method: 'POST',
data: $.param({grant_type: 'password', username: appSettings.username, password: appSettings.password }),
headers: {
'Content-Type': 'application/x-www-form-urlencoded' }
});
return resp;
};
return { login: this.login }
}
LoginController.js
app.controller('logincontroller', ['$scope', 'loginservice', 'userProfile', '$rootScope', logincontroller]);
function logincontroller($scope, loginservice, userProfile, $rootScope) {
$scope.title = 'logincontroller';
$scope.IniciarLogin = function () {
var loginResult = loginservice.login();
loginResult.then(function (resp) {
userProfile.setProfile(resp.data.userName, resp.data.access_token, resp.data.refresh_token);
}, function (response) {
alert("error");
});
}
$scope.logout = function () {
sessionStorage.removeItem('accessToken');
if (sessionStorage.getItem('userSessionName') != null){
sessionStorage.removeItem('userSessionName');
}
}
}
The web API token authentication was built as shown in the link below, I wont paste their entire code:
https://stormpath.com/blog/token-authentication-asp-net-core
In this part of code, you are trying add the configure cors after put the app variable into ConfigureAuth like parameter. Then, you should configure first the CORS and then pass the variable app into ConfigureAuth.
You can see in the code below:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseCors("SiteCorsPolicy");
app.UseMvc();
ConfigureAuth(app);
}
you specify app.UseCors("AllowAllHeader"); but your policy name is "AllowAllHeaders"
if you remove that line, your call to app.UseCors("AllowAllOrigins"); should handle everything (since you specify AllowAnyHeader() in the "AllowAllOrigins" policy

Categories