jwt auth scaffolding

logging in now works

UI login component created
pull/67/head
Isaac Grynsztein 6 years ago
parent da8571fb1a
commit 1f3572a630

@ -1629,9 +1629,14 @@ app.post('/api/fileStatusMp4', function(req, res) {
// gets all download mp3s
app.get('/api/getMp3s', function(req, res) {
const multiUserMode = config_api.getConfigItem('ytdl_multi_user_mode');
var mp3s = db.get('files.audio').value(); // getMp3s();
var playlists = db.get('playlists.audio').value();
if (req.query.jwt && multiUserMode) {
// mp3s = db.get
}
res.send({
mp3s: mp3s,
playlists: playlists
@ -2313,8 +2318,7 @@ app.get('/api/audio/:id', function(req , res){
app.post('/api/auth/register'
, auth.registerUser);
app.post('/api/auth/login'
// , auth.passport.authenticate('basic',{session:false}) // causes challenge pop-up on 401
, auth.authenticateViaPassport
, auth.passport.authenticate('local', {})
, auth.generateJWT
, auth.returnAuthResponse
);

@ -8,6 +8,15 @@ db.defaults(
}
).write();
var LocalStrategy = require('passport-local').Strategy;
var JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
var opts = {}
opts.jwtFromRequest = ExtractJwt.fromUrlQueryParameter('jwt');
opts.secretOrKey = 'secret';
opts.issuer = 'example.com';
opts.audience = 'example.com';
/*************************
* Authentication module
************************/
@ -23,11 +32,18 @@ const SERVER_SECRET = uuid();
exports.passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
exports.passport.serializeUser(function(user, done) {
done(null, user);
});
exports.passport.deserializeUser(function(user, done) {
done(null, user);
});
/***************************************
* Register user with hashed password
**************************************/
exports.registerUser = function(req, res) {
console.log('got here');
var userid = req.body.userid;
var username = req.body.username;
var plaintextPassword = req.body.password;
@ -76,10 +92,31 @@ exports.registerUser = function(req, res) {
* This checks that the credentials are valid.
* If so, passes the user info to the next middleware.
************************************************/
exports.passport.use(new BasicStrategy(
exports.passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
const user = db.get('users').find({uid: jwt_payload.sub}).value();
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
}));
exports.passport.use(new LocalStrategy({
usernameField: 'userid',
passwordField: 'password'},
function(username, password, done) {
const user = db.get('users').find({name: username}).value();
if (!user) { return done(null, false); }
if (user) {
return done(null, bcrypt.compareSync(password, user.passhash) ? user : false);
}
}
));
/*passport.use(new BasicStrategy(
function(userid, plainTextPassword, done) {
// console.log('BasicStrategy: verifying credentials');
const user = db.get('users').find({uid: userid}).value();
const user = db.get('users').find({name: userid}).value();
if (user) {
var hashedPwd = user.passhash;
return bcrypt.compare(plainTextPassword, hashedPwd);
@ -88,6 +125,7 @@ exports.passport.use(new BasicStrategy(
}
}
));
*/
/*************************************************************
* This is a wrapper for auth.passport.authenticate().
@ -96,6 +134,7 @@ exports.passport.use(new BasicStrategy(
* Browser's will pop-up up dialog when status is 401 and
* "WWW-Authenticate:Basic..."
*************************************************************/
/*
exports.authenticateViaPassport = function(req, res, next) {
exports.passport.authenticate('basic',{session:false},
function(err, user, info) {
@ -109,6 +148,7 @@ exports.authenticateViaPassport = function(req, res, next) {
}
)(req, res, next);
};
*/
/**********************************
* Generating/Signing a JWT token
@ -158,6 +198,12 @@ exports.ensureAuthenticatedElseError = function(req, res, next) {
}
}
// video stuff
exports.getUserVideos(type) {
}
function getToken(queryParams) {
if (queryParams && queryParams.jwt) {
var parted = queryParams.jwt.split(' ');

@ -4,11 +4,15 @@ import { MainComponent } from './main/main.component';
import { PlayerComponent } from './player/player.component';
import { SubscriptionsComponent } from './subscriptions/subscriptions.component';
import { SubscriptionComponent } from './subscription/subscription/subscription.component';
import { PostsService } from './posts.services';
import { LoginComponent } from './components/login/login.component';
const routes: Routes = [
{ path: 'home', component: MainComponent },
{ path: 'player', component: PlayerComponent},
{ path: 'subscriptions', component: SubscriptionsComponent },
{ path: 'subscription', component: SubscriptionComponent },
{ path: 'home', component: MainComponent, canActivate: [PostsService] },
{ path: 'player', component: PlayerComponent, canActivate: [PostsService]},
{ path: 'subscriptions', component: SubscriptionsComponent, canActivate: [PostsService] },
{ path: 'subscription', component: SubscriptionComponent, canActivate: [PostsService] },
{ path: 'login', component: LoginComponent },
{ path: '', redirectTo: '/home', pathMatch: 'full' },
];

@ -57,6 +57,7 @@ import { ArgModifierDialogComponent, HighlightPipe } from './dialogs/arg-modifie
import { UpdaterComponent } from './updater/updater.component';
import { UpdateProgressDialogComponent } from './dialogs/update-progress-dialog/update-progress-dialog.component';
import { ShareMediaDialogComponent } from './dialogs/share-media-dialog/share-media-dialog.component';
import { LoginComponent } from './components/login/login.component';
registerLocaleData(es, 'es');
export function isVisible({ event, element, scrollContainer, offset }: IsVisibleProps<any>) {
@ -85,7 +86,8 @@ export function isVisible({ event, element, scrollContainer, offset }: IsVisible
HighlightPipe,
UpdaterComponent,
UpdateProgressDialogComponent,
ShareMediaDialogComponent
ShareMediaDialogComponent,
LoginComponent
],
imports: [
CommonModule,

@ -0,0 +1,22 @@
<mat-card class="login-card">
<mat-tab-group>
<mat-tab label="Login">
<div style="margin-top: 10px;">
<mat-form-field>
<input [(ngModel)]="usernameInput" matInput placeholder="User name">
</mat-form-field>
</div>
<div>
<mat-form-field>
<input [(ngModel)]="passwordInput" type="password" matInput placeholder="Password">
</mat-form-field>
</div>
<div style="margin-bottom: 10px; margin-top: 10px;">
<button [disabled]="loggingIn" color="primary" (click)="login()" mat-raised-button>Login</button>
</div>
</mat-tab>
<mat-tab *ngIf="registrationEnabled" label="Register">
</mat-tab>
</mat-tab-group>
</mat-card>

@ -0,0 +1,6 @@
.login-card {
max-width: 600px;
width: 80%;
margin: 0 auto;
margin-top: 20px;
}

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,31 @@
import { Component, OnInit } from '@angular/core';
import { PostsService } from 'app/posts.services';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
usernameInput = '';
passwordInput = '';
registrationEnabled = true;
loggingIn = false;
constructor(private postsService: PostsService) { }
ngOnInit(): void {
}
login() {
this.loggingIn = true;
this.postsService.login(this.usernameInput, this.passwordInput).subscribe(res => {
this.loggingIn = false;
console.log(res);
}, err => {
this.loggingIn = false;
});
}
}

@ -5,12 +5,12 @@ import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import { THEMES_CONFIG } from '../themes';
import { Router } from '@angular/router';
import { Router, CanActivate } from '@angular/router';
import { DOCUMENT } from '@angular/common';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class PostsService {
export class PostsService implements CanActivate {
path = '';
audioFolder = '';
videoFolder = '';
@ -24,6 +24,10 @@ export class PostsService {
httpOptions = null;
debugMode = false;
isLoggedIn = false;
token = null;
user = null;
constructor(private http: HttpClient, private router: Router, @Inject(DOCUMENT) private document: Document) {
console.log('PostsService Initialized...');
// this.startPath = window.location.href + '/api/';
@ -41,6 +45,11 @@ export class PostsService {
}),
};
}
canActivate(route, state): boolean {
console.log(route);
return true;
throw new Error('Method not implemented.');
}
setTheme(theme) {
this.theme = this.THEMES_CONFIG[theme];
@ -233,4 +242,27 @@ export class PostsService {
return this.http.get('https://api.github.com/repos/tzahi12345/youtubedl-material/releases');
}
afterLogin(user, token) {
this.isLoggedIn = true;
this.user = user;
this.token = token;
this.httpOptions = {
params: new HttpParams({
fromString: `apiKey=${this.auth_token}&jwt=${this.token}`
}),
};
}
// user methods
login(username, password) {
const call = this.http.post(this.path + 'auth/login', {userid: username, password: password}, this.httpOptions);
call.subscribe(res => {
if (res['token']) {
this.afterLogin(res['user'], res['token']);
}
});
return call;
}
}

Loading…
Cancel
Save