mlangwell
mlangwell

Reputation: 345

How to properly use user registration in ServiceStack

I am new to ServiceStack and I am having some problems truly understanding the user registration stuff. Our goal is to:

  1. Allow a user to create a new account
  2. Verify if a user name and/or email is already in use
  3. Automatically log the user in after registering
  4. Return JWT token with response

I am currently using the RegisterService located here for all of our user registration logic.

The problem seems to be that after a user registers any other user can register with the same user name and/or email and all it does is updates the previous users data. I have noticed that when I restart the API that the line:

RegistrationValidator?.ValidateAndThrow(request, registerNewUser ? ApplyTo.Post : ApplyTo.Put);

will throw an error if a user name or email already exists. However, as I just explained once a new user registers, another user right after them can use the exact same info and all it does is updates the user before it. This is not the desired result.

Why does the validation seem to work if I restart the API, but not while it is running?

As I step through the code I have noticed that this.GetSession() seems to return a new session with basically everything set to null when the API is first started, but once a user logs in or registers GetSessions() returns the most recent user session.

I apologize in advance if I come off like I know nothing, like I said I am very new to ServiceStack and I have pretty much spent the past couple of days at work trying to figure this out. I have scoured many forums including ServicStacks customer forums and even here. Any advice would be appreciated!

Upvotes: 2

Views: 686

Answers (1)

mythz
mythz

Reputation: 143319

The problem seems to be that after a user registers any other user can register with the same user name and/or email and all it does is updates the previous users data.

Only the current user can update their User Registration Info after they're registered. You can return to being an Unauthenticated the user out by calling /auth/logout to clear their session or if using a Service Client:

client.Post(new Authenticate { provider = "logout" });

Why does the validation seem to work if I restart the API, but not while it is running?

Because the User is authenticated and you're using the default In Memory Cache Client where Sessions are saved to and restarting the App Domain clears all User Sessions so all previously authenticated are now unauthenticated.

There's a few different options to achieve your desired outcome:

Register then Authenticate the user

  1. Use the Register Service to create a new Account. The Registration Service will throw if the Username or Email is in use.

  2. On successful registration, call the Authenticate Service (/auth/credentials) to authenticate the user using the new credentials. If the JWT AuthProvider is registered and it's called using https or the JWT Auth Provider is configured with RequireSecureConnection=false it will return the JWT Token and Refresh Token.

If you Authenticate with UseTokenCookie=true then the Authenticated UserSession is converted into a JWT Token and returned in the ss-tok Cookie.

Register the user with AutoLogin then convert Session to Token

Auto login with the Register Service, calling the Register Service with AutoLogin=true will authenticate the User after registering them in the same request, but the RegisterResponse DTO that the Register Service returns doesn't contain the JWT Token, instead you can call /session-to-token to convert the current authenticated User Session into a JWT Token which is returned in the ss-tok Cookie which is sent with subsequent requests to make authenticated requests.

Register the user with AutoLogin with latest version

I've just added support for returning the JWT Token and Refresh Token in AutoLogin Register Requests in this commit so you can just register the User with:

var response = client.Post(new Register {
    //...
    AutoLogin = true
});

And you'll be able to access the JWT tokens in:

response.BearerToken   //JWT Token
response.RefreshToken  //JWT RefreshToken

This change is available from v4.5.15 that's now available on MyGet.

Upvotes: 1

Related Questions