ronzeidman / ng2-ui-auth-example

MIT License
34 stars 14 forks source link

Few questions #6

Closed aegyed91 closed 7 years ago

aegyed91 commented 7 years ago

Hi @ronzeidman!

The error TS throws: Incompatible override for member from AuthService.

Also nothing depends on these methods internally so the return type doesnt matter in this case.

export class AuthService extends NgAuthService {
  // ...
  // any idea how can i keep the method name `signup` and tell TS i know what i am doing and stop throwing errors because of this?
  oSignup(user, opts?: RequestOptionsArgs): Promise<{ token: string, user: IUser }> {
    return super.signup(user, opts).toPromise().then(res => res.json());
  }
ronzeidman commented 7 years ago

Hi,

1 - you can check the scopes, in this library you just use minimal scopes to get the client basic info for authentication and it's done on the server-side, the client doesn't actually get the "google/facebook/twitter" token. There you can check the scope before using the API or like I did fail for no reason if the scope does not contain the required permissions.

2 - I started with also setting the token by default on the signup method but then people (myself included) usually do something else before letting the user in (like validating email), if you want you can easily add the do yourself.

3 - Yea, it's an issue... I just wanted the user to get full auto-completion when he uses these methods, I'll think about how to make it more plugable, if you really want to do that you could probably replace the module (https://github.com/ronzeidman/ng2-ui-auth/blob/master/src/ng2-ui-auth.module.ts) and fully provide your class, but then you'll need to copy&paste all the functions you actually need, or just do another wrapper instead of extending the existing one.

If you have any suggestions how to improve the library/example feel free to pull request or add a comment to this issue.

aegyed91 commented 7 years ago

thx for the info, I got all my questions answered

about qnr3, its really an issue with typescript. You should be able to ad-hoc shut type checker up.

new question: how are you able to grab the payload encoded into the jwt hash with SharedService#getPayload? Some basic concept or something is very unclear. I thought you need a secret key in order to decode it and read its contents. Instead this 3 line decodes this token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImF0dGlsYS5lZ3llZC45MUBnbWFpbC5jb20iLCJzY29wZSI6WyJ1c2VyIl0sImlhdCI6MTQ4MDAwOTE5MSwiZXhwIjoxNDgyNjAxMTkxfQ.ZQ2yycb1IX7YsqHUIpjQ2dASZCJs8CQ2rkH8E0unpd8 in the browser console w/o any problem. I encoded that has with a secret key here.

Also what do you think about security reasons? You could use cookies for the local authentication scheme. HTTP only wont even let JS touch it and it works on the browser level. I guess cookies too work in cordova based apps, because they run in a webview. I would use oauth2 auth in local scheme when the localscheme is not like 1api, 1socket server but a bunch of servers with microservice architecture.

One more basic concept thing I don't get:

I encode the whole user object in the jwt token? Wont the token grow big? User object could have many-many properties. And because it is stateless I have to send with each http request. Making http traffic bigger.

Oter option is to encode some unique identifier only, like email addr. I could query for the user serverside send it bk from a route like user/profile. Save it on the client side and keep it sync with the one in db. (more code, more error prone (the syncing part))

option 1 is much better, but I wonder how much bigger the http traffic gets.

I am also not perfectly familiar with the cookie system either. maybe the very same happens there just on browser lvl.

ronzeidman commented 7 years ago

The payload is encoded in base64, its not encrypted so anyone can read it. But it is signed, so no one can manipulate it. You need the private key to change the content of the payload. The JWT token is comprised of three parts seperated by "." and encoded in base 64 the header, payload and signature. you should validate at the server-side if the signature represents the header+payload and then read the payload. The jwt token payload should store the most-used fields so the server could do less database jumps, like the user ID and permissions, anything else will bloat your token. with cookies you have to store a session in the server-side and maintain it, with the JWT token you don't need that, that's the main difference and the power of this token. I hope I answered everything. Feel free to ask again if not.

aegyed91 commented 7 years ago

Alright, i live with the opportunity then :D

So here is what i came up with about token based stateless auth management:

q1, so here if the validateFunc gets called i am already certain the token was legit and signed by me. I dont have to query the user from db right? The middleware is called hapi-auth-jwt2. It does verify the token but dont attach the payload to the request object like express-jwt

q2, lets get a scenario when i should change something in the token (most likely scopes). Lets say i make an user to admin / moderator. That means old access tokens will have outdated permission information about the user and on top of that i didn't put an expiration date when created the token. What happens then?

i guess there are 2 scenarios, the 1st is what you used in the example app: always put an expiration time on the token (like 15mins) and create a route (/refresh) to extend the life of the token. Poll that route every now and then. 2nd option is lot harder / slower / error prone so i guess it is not suggested: create a database table and keep track of all the tokens you ever created, add an extra column called is_valid. This way you can invalidate a token. But you need to manage this, like cookie sessions.

ronzeidman commented 7 years ago

Seems like you've got it. q1) Usually you get the decoded token on the server-side after the validation, I guess the "strategy" function verifies the token with your secret before calling validateFunc, so you don't need to call the db for it. q2) You should put an expiration date on the token, if not anyone with that specific token would be able to access your site indefinitely. There is a concept of no-expiration-date tokens usually used in the mobile world (since they can store them in a secure location) but then you'll have to store a token ID in a persistent storage so you could further validate and revoke them if needed, this would make you have to call the DB for each call so usually they are used as "refresh token"s and with them you could get a temporary regular token so you won't have to call the DB for each call, only for the refresh.

aegyed91 commented 7 years ago

Thx a lot for the clarification. I dont feel lost anymore.

I going to close this.

I'll open separate issues if there is anything i'll recognize on my journey of user management that concerns this library.