Dhruv Korwala
Dhruv Korwala

Reputation: 23

How to update token using refresh token in MVC Client Application?

There are two type of application in my solution 1)Web api application 2)MMC c# application

Here I created web api application which has facility of token authentication. In this Application username and password validating from SQL server database. i.e If any user request for web api token that user detail must be present in database table.(In user Table Id,Username,Password column are there with data). So my web api application connected to database server.

Now I created MVC c# application which consume web api and access the data. what I do here that when user put credential to mvc app login screen and that credential goes to api and validate them. Api will give response of data If user credential are correct.

Here I got JSON response from web api and data like "access_token","Expire_time","refresh_token" etc I stored all these detail in Session object.

So whenever I request for Getdata() from mvc app I passing 'access_token' to api and retuned result data.

I set web api token timeout 2 minutes.(token get deleted after 2 minutes)

So problem goes here that how I can maintain user login session in web api using refresh_token.I do not want to user again get login screen and come back to that screen. Because every 2 minutes he will get login screen which is not correct solution.

I want some function when api get timeout access_token and mvc application again call refresh_token and continue data transaction.

Upvotes: 1

Views: 5348

Answers (1)

Deepankshee Jain
Deepankshee Jain

Reputation: 131

Whenever your accesstoken is expired you can pass refresh token and can update the access token like this. Hope this will help you.

[AllowAnonymous]
        [HttpPost]
        public IHttpActionResult GetAccessToken(RefreshTokenModel getRefreshToken)
        {
            ApiResponse apiResponse = new ApiResponse();
            apiResponse.Message = "Your session has expired. Kindly login again.";
            try
            {
                var getHashToken = GenerateHash.GetHash(getRefreshToken.RefreshToken);
                var getRefreshTokenDetails = tokenDetailBl.GetRefreshTokenDetail(getHashToken);
                if (getRefreshTokenDetails != null && getRefreshTokenDetails.ExpiresUtc > DateTime.UtcNow && !string.IsNullOrEmpty(getRefreshTokenDetails.ProtectedTicket))
                {
                    if (getRefreshTokenDetails.DeviceType == getRefreshToken.DeviceType)
                    {
                        var currentTime = DateTime.UtcNow;
                        var refreshTokenLifeTime = Convert.ToDouble(ConfigurationManager.AppSettings["RefreshTokenExpireTime"]);
                        var tokenExpiration = Convert.ToDouble(ConfigurationManager.AppSettings["AccessTokenExpireTime"]);
                        ApiIdentityManager apiIdentityManager = new ApiIdentityManager();

                        var tokenData = JsonConvert.SerializeObject(new { Ticket = getRefreshTokenDetails.ProtectedTicket, DeviceId = getRefreshTokenDetails.DeviceId });
                        var getIdentityToken = apiIdentityManager.GetRefreshToken(tokenData);

                        // Delete Old Tokens
                        tokenDetailBl.DeleteAccessTokenByDevice(getRefreshTokenDetails.DeviceId);
                        var refreshToken = new RefreshToken()
                        {
                            RefreshTokenId = GenerateHash.GetHash(getIdentityToken.RefreshToken),
                            DeviceId = getRefreshTokenDetails.DeviceId,
                            DeviceType = getRefreshToken.DeviceType,
                            UserId = getRefreshTokenDetails.UserId,
                            IssuedUtc = currentTime,
                            ExpiresUtc = currentTime.AddMinutes(Convert.ToDouble(refreshTokenLifeTime)),
                            ProtectedTicket = getIdentityToken.Ticket
                        };

                        //Save new tokens
                        tokenDetailBl.SaveAccessToken(new TokenDetail
                        {
                            AccessToken = getIdentityToken.AccessToken,
                            CreatedOn = DateTime.UtcNow,
                            UserId = getRefreshTokenDetails.UserId,
                            DeviceId = getRefreshTokenDetails.DeviceId,
                            DeviceType = getRefreshToken.DeviceType
                        });
                        tokenDetailBl.SaveRefreshToken(refreshToken);

                        //Get token cache.
                        CachedData cachedData = new CachedData(tokenDetailBl);
                        var getAllToken = cachedData.GetAccessTokens();
                        cachedData.UpdateTokenCache(getIdentityToken.AccessToken, getRefreshTokenDetails.UserId + ":" + DateTime.UtcNow.AddMinutes(tokenExpiration).ToFormateDateTimeString());

                        var getUserDetails = userBl.GetUserDetails(getRefreshToken.UserId);
                        getUserDetails.DeviceId = getRefreshTokenDetails.DeviceId;
                        getUserDetails.DeviceType = getRefreshTokenDetails.DeviceType;
                        getUserDetails.AccessToken = getIdentityToken.AccessToken;
                        getUserDetails.TokenType = "bearer";
                        getUserDetails.ExpiresIn = getIdentityToken.ExpiresIn;
                        getUserDetails.Issued = getIdentityToken.Issued;
                        getUserDetails.Expires = DateTime.UtcNow.Add(TimeSpan.FromMinutes(tokenExpiration)).ToString("R");
                        getUserDetails.RefreshToken = getIdentityToken.RefreshToken;



                        //Dictionary<string, string> tokenResponse = new Dictionary<string, string>();
                        //tokenResponse.Add("access_token", getIdentityToken.AccessToken);
                        //tokenResponse.Add("token_type", "bearer");
                        //tokenResponse.Add("expires_in", getIdentityToken.ExpiresIn);
                        //tokenResponse.Add("issued", getIdentityToken.Issued);
                        //tokenResponse.Add("expires", DateTime.UtcNow.Add(TimeSpan.FromMinutes(tokenExpiration)).ToString("R"));
                        //tokenResponse.Add("refresh_token", getIdentityToken.RefreshToken);
                        return ResponseMessage(Request.CreateResponse(HttpStatusCode.OK, getUserDetails));
                    }
                    else
                    {
                        apiResponse.Message = "Your session has expired. Kindly login again.";
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }

            return ResponseMessage(Request.CreateResponse(HttpStatusCode.Gone, apiResponse));
        }

You can use MVC filters to check that your access token is expired or not something like this.

[CacheAuthorize]
    [HttpPost]
    public IHttpActionResult GetUserList(SearchRequest searchRequest)

and after that code to check validation of access token

 public class CacheAuthorizeAttribute : AuthorizeAttribute
        {
            public CacheAuthorizeAttribute(params string[] roles)
                : base()
            {
                Roles = string.Join(",", roles);
            }

            public override void OnAuthorization(HttpActionContext actionContext)
            {

                Dictionary<HttpStatusCode, string> response;
                if (SkipAuthorization(actionContext))
                {
                    return;
                }

                var userSessionManager = new UserCacheManager();
                if (userSessionManager.ReValidateSession(out response))
                {
                    base.OnAuthorization(actionContext);
                }
                else
                {
                    ApiResponse apiResponse = new ApiResponse(response.Values.FirstOrDefault());
                    actionContext.Response = actionContext.ControllerContext.Request.CreateResponse(response.Keys.FirstOrDefault(), apiResponse);
                }


 }


/// <summary>
        /// Re-validates the user session. Usually called at each authorization request.
        /// If the session is not expired, extends it lifetime and returns true.
        /// If the session is expired or does not exist, return false.
        /// </summary>
        /// <returns>true if the session is valid</returns>
        public bool ReValidateSession(out Dictionary<HttpStatusCode, string> errorResponse)
        {

            errorResponse = new Dictionary<HttpStatusCode, string>();
            string authToken = this.GetCurrentBearerAuthrorizationToken();
             ITokenDetailRepository tokenDetailRepository = new TokenDetailRepository();
             ITokenDetailBL tokenDetailBl = new TokenDetailBL(tokenDetailRepository);
             CachedData cachedData = new CachedData(tokenDetailBl);
            if (!string.IsNullOrEmpty(authToken))
            {
                var currentUserId = this.GetCurrentUserId();
                var getUserTokens = cachedData.GetAccessTokens();
                if (!getUserTokens.ContainsKey(authToken))
                {
                    //Get Data from DB
                    cachedData.GetAccessToken(authToken);
                    getUserTokens = cachedData.GetAccessTokens();
                }
                return CheckAccessToken(getUserTokens, authToken, out errorResponse);
            }
            else
            {
                errorResponse.Add(HttpStatusCode.Gone, "Access token not found.");
            }
            return false;
        }

 private bool CheckAccessToken(Dictionary<string, string> accessTokenDictionary, string authToken, out Dictionary<HttpStatusCode, string> errorResponse)
        {
            errorResponse = new Dictionary<HttpStatusCode, string>();
            var hasToken = accessTokenDictionary.ContainsKey(authToken);

            if (hasToken)
            {
                var getTokenValue = accessTokenDictionary[authToken];
                var enCulture = new CultureInfo("en-US");
                DateTime tokenAddedDate;
                var isCorrectDate = DateTime.TryParseExact(getTokenValue.Split(new char[] { ':' }, 2)[1], "dd-MMM-yyyy,hh:mm tt", enCulture, DateTimeStyles.None, out tokenAddedDate);
                if (isCorrectDate)
                {
                    if (tokenAddedDate >= DateTime.UtcNow)
                    {
                        return true;
                    }
                    else
                    {
                        //Check Refresh token expired or not
                        errorResponse.Add(HttpStatusCode.Unauthorized, "Access token expired.");
                    }
                }
                else
                {
                    errorResponse.Add(HttpStatusCode.Gone, "Invalid access token.");
                }
            }
            else
            {
                errorResponse.Add(HttpStatusCode.Gone, "Invalid access token.");
            }
            return false;
        }

Upvotes: 1

Related Questions