I have an angular 2 app with JWT authentication (Auth0) that after user login stores the profile and token id in the localStorage, the profile contains a "role" attribute to check if the user can access an especific page.
Everything works like a charm but if the user change the role property in the localStorage to "admin" for example and reload the app he can access pages that he is not authorized. How can I handle that?
auth.service.ts:
declare var Auth0Lock: any;
#Injectable()
export Class AuthService {
lock = new Auth0Lock(ID, domain);
user: Object;
constructor() {
this.user = JSON.parse(localStorage.getItem('profile'));
}
public login() {
// Auth0 method
this.lock.show({}, (err: string, profile: Object, token: string) => {
if (err) { console.log(err); return; }
localStorage.setItem('profile', JSON.stringify(profile));
localStorage.setItem('id_token', token);
});
}
public logout() {
localStorage.removeItem('profile');
localStorage.removeItem('id_token');
}
public loggedIn() {
return tokenNotExpired();
}
public isAdmin() {
if (this.user['role'] == 'admin') {
return true;
} else {
return false;
}
}
}
app.component.ts:
// imports, etc
export Class AppComponent {
constructor(private auth: AuthService) {}
}
app.component.html:
<nav>
<ul>
<li><a [routerLink]="['Customers']" *ngIf="auth.loggedIn()">Customers</a></li>
<li><a [routerLink]="['Admin']" *ngIf="auth.loggedIn() && auth.isAdmin()">Admin</a></li>
</ul>
</nav>
Any ideas to handle that would be appreciated
In my opinion, it's impossible to create fully secured pages/forms, when you have JavaScript front-end framework. I mean, there is always possibility to open any form, when all application is downloaded to and constructed at client side.
For me, it's important to secure back-end api, and leave "hacking" opportunities to junior developers.
If you have such requirements, try to use server side generated framework: php, asp.net mvc, jsp & etc.
UPDATE
As it came up, Angular2 has directive #CanActivate, which gives more accurate way to cancel navigaition. BUT server side authorization is CRITICAL in javascript front-end based applications.
This will help how to deal with JWT in express back-end: express-jwt
Related
I am new to Angular, and trying to connect this sample app to my API gateway, which is a ContactApp.
Currently it works on mock API and I want to use an actual api server. I have done all the steps from this website but it seems like a wrong approach, It didn't work. Can someone explain how I should configure it?
here is the request call for getContacts
getContacts(): Observable<Contact[]>
{
return this._httpClient.get<Contact[]>('api/apps/contacts/all').pipe(
tap((contacts) => {
this._contacts.next(contacts);
})
);
}
and here is the mock api reply:
this._MockApiService
.onGet('api/apps/contacts/all')
.reply(() => {
// Clone the contacts
const contacts = cloneDeep(this._contacts);
// Sort the contacts by the name field by default
contacts.sort((a, b) => a.name.localeCompare(b.name));
// Return the response
return [200, contacts];
});
All I need is an explanation of steps I should follow to migrate MOCK API to cloud..or any similar project?
You can simply do this:
On your .ts file:
//your imports
import { HttpClient, HttpBackend } from "#angular/common/http";
//
export class YourComponent implements OnInit{
contacts:any;
...
//your constructor
constructor(private http: HttpClient)
//initialize the function here
ngOnInit(): void {
this.getContacts()
}
//your function to get the contacts API data
getContacts(){
return this.http.get("your API endpoint")
.subscribe((contacts: any) => {
this.contacts= response;
});
}
then on your .html file, bind the data
<p *ngFor="let contacts of contacts">{{contacts.name}}</p>
I have an identity server 4 implementation very simple and I'm using the oidc-client on my angular APP to carry on all the security management. In my auth service I have the following:
#Injectable()
export class AuthService {
private manager: UserManager;
private user: User = null;
constructor() {
if (!environment.production) {
Log.logger = console;
}
this.manager = new UserManager(getClientSettings());
this.manager.getUser()
.then(user => {
this.user = user;
});
this.manager.events.addUserSignedOut(() => {
this.user = null;
this.signOut();
});
}
signOut(): Promise<void> {
return this.manager.signoutRedirect()
.then(() => {
this.manager.clearStaleState();
});
}
...more
}
export function getClientSettings(): UserManagerSettings {
return {
authority: environment.authorityUrl,
client_id: 'myclient',
redirect_uri: `${environment.baseUrl}/auth-callback`,
post_logout_redirect_uri: environment.baseUrl,
response_type: 'id_token token',
scope: 'openid profile myapi',
filterProtocolClaims: true,
loadUserInfo: true,
automaticSilentRenew: true,
revokeAccessTokenOnSignout : true,
silent_redirect_uri: `${environment.baseUrl}/silent-renew-callback`,
};
}
Everything works like a charm so I can log in/out without any issues, the token renewal works as expected and so far so good. However I decided to implement a "custom" behavior when a user open the application in multiple tabs on the same browser and one of them logs out. Then the event UserSignedOut is triggered and I sign out the rest of the tabs that may be open. The problem I have is that when the user comes back in, the FIRST login attempt is performed correctly, however any subsequent login request from any other tab results in a 400 - BAD REQUEST (removing the Antiforgery token attribute from the login method in my IS4 it then works but I don't want to do so).
If you did refresh the tab then you get logged in therefore to me it seems something wrong with the actual state itself?
I'm not sure if I should invoke any other method in my AuthService prior logging out or whether I should re-implement the ValidateAntiForgeryToken with a custom behavior for this.
Any help is much appreciated, thanks!
I am using the Auth0-js package v9.1 to connect to my React app to a Hosted Page, which internally using Auth0Lock to customize user signup parameters.
What I would like to do is have a link to go to the login tab, and a separate button to connect directly to the Sign Up tab. Is this kind of control possible?
I have a AuthService wrapper class which I'm using to launch the Auth0 Lock client currently.
export class AuthService() {
constructor() {
this.auth0 = new auth0.WebAuth(
{
domain: AUTH0_DOMAIN,
clientID: AUTH0_CLIENT_ID,
redirectUri: AUTH0_REDIRECT_URL,
audience: AUTH0_AUDIENCE_URL,
responseType: 'token id_token',
scope: 'openid profile email'
}
)
}
isAuthenticated() {
// Check whether the session has past the
// access token's expiry time
return ( ! this.isSessionExpired() )
}
// display the Auth0 lock modal and allow the user to log in
login() {
this.auth0.authorize()
}
...
}
export default new AuthService
What I would like to have is a method which links directly to the Sign Up tab, so I can call it from a specialize component
....
signup() {
this.auth0.authorize('signup')
- or alternatively -
this.auth0.signup()
}
....
Is something like this possible? How would I go about linking directly to that Sign Up tab?
Thx
I handle authentication in my Ionic app with a Service. I would like to have View separated from Service. I have a function in auth service to fetch user. If user is not available in memory or database, I want the user to be redirected to Login page. This getUser function is used in different components.
getUser(){
if (this.user) {
return Promise.resolve(this.user) ;
} else {
return this.storage.get('user').then( (user) => {
if (user){
this.user = user;
return user
} else {
\\ way to prompt login page here.
}
})
.catch( this.handleError )
}
}
I would like to have something like a base component to handle login page push when user is not available. As far as I know angular doesn't support component inheritance. How can I achieve the functionality ? What I was thinking was a Subject emitted when no user is available. And the base component subscribe to this subject . How can I achieve this in Ionic ?
I'm trying to write a login solution for my Angular App,
This means to allow the user to connect via Facebook/Google/Twitter or Register normally.
I found Angular-OAuth to be useful, but it didn't seem to work with Facebook (or Twitter).
Anyone knows of an all-inclusive solution for this?
Here is a simple example using just redirects with angular js
Here is how to redirect to authentication
angular.module('angularoauthexampleApp')
.controller('MainCtrl', function ($scope) {
$scope.login=function() {
var client_id="your client id";
var scope="email";
var redirect_uri="http://localhost:9000";
var response_type="token";
var url="https://accounts.google.com/o/oauth2/auth?scope="+scope+"&client_id="+client_id+"&redirect_uri="+redirect_uri+
"&response_type="+response_type;
window.location.replace(url);
};
});
Here is how to handle the redirect after authentication
angular
.module('angularoauthexampleApp', [
])
.config(function ($routeProvider) {
$routeProvider
.when('/access_token=:accessToken', {
template: '',
controller: function ($location,$rootScope) {
var hash = $location.path().substr(1);
var splitted = hash.split('&');
var params = {};
for (var i = 0; i < splitted.length; i++) {
var param = splitted[i].split('=');
var key = param[0];
var value = param[1];
params[key] = value;
$rootScope.accesstoken=params;
}
$location.path("/about");
}
})
});
More complete information here http://anandsekar.github.io/oauth2-with-angularjs/
Take a look at oauth.io
Easy implementation in Javascript
80+ OAuth providers
Fast & secure
There is a Free-Open-Source alternative to the freemium oauth.io: hello.js
Have a look at the Satellizer project on Github. I'm just getting started with it, it seems promising.
It uses JSON Web Tokens, and allows login with: email+password, Facebook, Twitter, Google, and any other OAuth 1.0/2.0 provider.
The client side code works out the box, you'll have to implement the server side yourself. There are good descriptions of the work flows and code examples for many server side languages.
Just wanted to add some comment and sample Angular code for the OAuth.io solution mentioned above.
As the founder stated, it is a paid service but it has 2 main benefits I believe:
It provides a consistent way to connect to any OAuth provider be it Facebook, Twitter, etc., i.e.,it hides all the peculiarities of each OAuth provider implementation.
It enables you implement OAuth social buttons using only front-end code.
The front-end code is also rather simple. I took this from coderwall.
import {Component, OnInit} from '#angular/core';
function _window(): any {
// return the global native browser window object
return window;
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
ngOnInit(): void {
const oauthScript = document.createElement('script');
oauthScript.src = 'https://cdn.rawgit.com/oauth-io/oauth-js/c5af4519/dist/oauth.js';
document.body.appendChild(oauthScript);
}
handleClick(e) {
// Prevents page reload
e.preventDefault();
// Initializes OAuth.io with API key
// Sign-up an account to get one
_window().OAuth.initialize('YOUR OAUTH.IO PUBLIC KEY');
// Popup Github and ask for authorization
_window().OAuth.popup('github').then((provider) => {
// Prompts 'welcome' message with User's name on successful login
// Check console logs for additional User info
provider.me().then((data) => {
console.log('data: ', data);
alert('Welcome ' + data.name + '!');
});
// You can also call Github's API using .get()
provider.get('/user').then((data) => {
console.log('self data:', data);
});
});
}
}