0
votes

I have net core web application targeting an API and authenticating with Identity Server(also as web application). Because application is web server based, I have problem with storing access token from Identity Server which application needs in every request(in Header) in order to communicate with API. An ideal flow is: user launchs application and being prompt to enter his phone number(in order to get OTP code and authenticate), when submits phone number Identity Server with some external providers sends OTP code to user and now user is being prompt to enter OTP code. After successuflly submits OTP code, Identity Server verifies it and give access token to client. And this is point where problem starts.

First I tried to store access token with singleton that after otp validation stores(in some dictionary) access token related with phone number as key. But, problem is because application is webserver based and in production on server it is not mandatory that each user will have his application instance running on server, so singleton is useless beacese most likely we have at example 3-4 application running for 20 users and in that situation more than one users uses same singleton! Then I googled and found that best option is to store access token or some realted keys for that token in browser session or document cookie. So now application is working in way that after OTP code validation user's phone number and access token stores in Dictionary collection(now more users use same collection, beacuse singleton is useless for this) where key is phone number and access token is value, then javascript triggers and set user phone number in cookie(in each request) and now when creating Bearer header I simply read cookie from current reqeust and with that phone number i take access token from collection. So this solution is very bad because everything(after logging in) that you need to get access token is to modify phone number in cookie and if you are lucky and match some existing number in collection you will get access token and easily get access to API.

Down below is method that is being called in each request in order to get access token from collection where access token with phone number was put after otp validation.

public async Task<string> GetAccessToken()
        {
            string phoneNumber = GetUserPhoneNumber();

            if (string.IsNullOrEmpty(phoneNumber))
                throw new ArgumentNullException(nameof(phoneNumber));

            if (_usersTokenStore == null || _usersTokenStore.Count == 0)
                throw new NotImplementedException(nameof(_usersTokenStore));

            var refSingleUser = new SingleUserTokenStore();
            bool userHaveAccessToken = _usersTokenStore.TryGetValue(phoneNumber, out refSingleUser);

            if (!userHaveAccessToken)
                throw new Exception($"User with {phoneNumber} not authorized.");

            if (refSingleUser.IsTimeToRefreshToken)
               return await RefreshAndGetAccessToken();

            return refSingleUser.AccessToken;
        }


private string GetUserPhoneNumber()
        {
            if (_httpContext == null)
                throw new ArgumentException(nameof(_httpContext));

            var phoneNumberCookie = _httpContext.HttpContext.Request.Cookies.Where(c => c.Key == "phone_number").FirstOrDefault();

            if (phoneNumberCookie.Value == null || phoneNumberCookie.Key == null)
                return null;

            return phoneNumberCookie.Value;
        }
1

1 Answers

0
votes

It's unclear what you're doing here. If this is a web application (i.e. the user is presented with HTML views that they navigate between in a web browser), then you need to employ cookie authentication. There is no way for the user of a web browser to pass an Authorization header with each request. Cookie auth is the only way to persist authentication in a web browser.

If this is an API, then it is on the client to store the access token and submit it along with each request via the Authorization header.

In either case, you should not persist the auth token server-side. That is not the responsibility of the server.