How to refresh token in Adal? - azure

Hi I am developing web application in Angular 5. I am using azure active directory authentication oauth 2.0 implicit flow for Login. After 1 hour my application redirects to login page because i handled this in code as below.
protected handleError(error, continuation: () => Observable<any>) {
if (error.status == 401) {
this.appContextService.redirectForLogin();
//return Observable.throw(error);
}
else if (error.url && error.url.toLowerCase().includes(this.loginUrl.toLowerCase())) {
return Observable.throw((error.error && error.error.errormessage) ? `session expired (${error.error.errormessage})` : 'session expired');
}
else {
return Observable.throw(error);
}
}
redirectForLogin() {
this.loginRedirectUrl = this.router.url;
this.router.navigate(['']);
this.adalSvc.login();
}
After one hour i want user not to enter password again. I want to implement refresh token mechanism here. Can someone help me to fix this. Thank you.

Related

Getting a Azure AD refresh token and auth code using MSAL

I am working on an application with Ruby on Rails back-end and EmberJS Front-end.
I would like to achieve the following.
Log in user with MSAL with Ember FE
Get the auth_code and pass on to the back end
From the back end, fetch access token and refresh token.
Use it to send email using azure Graph API.
Basically I would like to perform step 1 of azure ad auth, i.e. fetching the auth_code, at the front end. And then perform step 2 at the back end. And then refresh the tokens at the back-end as needed.
I believe MSAL provides no good way to achieve this. When user consents (Step 1), it uses the auth_code by itself to fetch access_token and refresh_token (Step 2), and cashes it without exposing the values. It invokes acquireTokenSilent method to refresh the tokens when needed.
I can see that MSAL also has a ssoSilent method, which performs only step 1 of auth and returns auth code. I tried to use it in the following manner
signIn = () => {
myMSALObj
.loginPopup(loginRequest)
.then(this.handleResponse)
.catch((error) => {
console.error(error);
});
};
handleResponse = (resp) => {
console.log('>>>> Response', resp);
// this.token = resp;
if (resp !== null) {
username = resp.account.username;
// showWelcomeMessage(resp.account);
resp.account = myMSALObj.getAccountByUsername(username);
console.log('Resp => ', resp);
myMSALObj
.ssoSilent(resp)
.then((r) => {
console.log(r);
})
.catch((e) => {
console.log('Error ->', e);
});
} else {
// loadPage();
}
};
This always ends up in the following error
InteractionRequiredAuthError: interaction_required: Silent authentication was denied. The user must first sign in and if needed grant the client application access to the scope ...
Even when the user has just consented for these scopes.
Is there something I am missing?
or
Is there any better way to achieve this functionality?
Thanks in advance for any help
I am using Rails 6 with Ember 4.1

How to make condition on context.get in Dialogflow fulfillment?

I want to make if else condition on token if token is null or undefined or "" then it will redirect on event and if token comes from context.get than it will show token exist.
Please check my code but its not working its going to crash every time. Please help me out to get any solution.
function RaiseQuery(agent) {
let token = "";
const infoContext = agent.context.get('info');
token = infoContext.parameters.token;
if (token === null){
agent.setFollowupEvent("Login");
} else {
agent.add("Token Exist");
}
}
Logs:
Thank You

Firebase Realtime Database Rules Denying Permission

I have an application I am building in Kotlin, with a backend in Node.js.
I am allowing users to login/signup using Firebase Authentication on the client application.
Part of the functionality of the application, is to let users save data online through Firebase's real time database. What happens inside the application, is once a user is logged in, I am passing his/her uid to the backend, which makes a request to the database.
Everything was working fine when the rules for the database were to allow read/write to everyone.
Once I changed them to this:
{
"rules": {
"users": {
".read": "auth != null && auth.uid != null",
".write": "auth != null && auth.uid != null",
}
}
}
I keep getting Permission Denied.
I have tried different variations of the rules:
Without the users key
Only checking that auth is not null
but none seem to work.
Is there some step I am missing?
I have combed over many similar StackOverflow questions and Firebase's real time database documentation, but have not found an answer to my problem.
Some code for reference:
Backend:
app.get('/someRoute', function (req, res) {
var database = firebase.database()
var uid = req.query.uid
database.ref('/users/' + uid).once('value')
.then(function(snapshot) {
var data = snapshot.val() ? snapshot.val() : []
res.status(200).send({ response: data})
}).catch(function(error) {
console.log(error)
res.status(500).json({ error: error})
})
})
Client:
fun loginUser(view : View) {
FirebaseAuth.getInstance().signInWithEmailAndPassword(userEmail, userPassword)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
updateFirebaseUserDisplayName()
} else {
Toast.makeText(this, "An error has occurred during login. Please try again later.", Toast.LENGTH_SHORT).show()
}
}
}
fun updateFirebaseUserDisplayName() {
FirebaseAuth.getInstance().currentUser?.apply {
val profileUpdates : UserProfileChangeRequest = UserProfileChangeRequest.Builder().setDisplayName(userEmail).build()
updateProfile(profileUpdates)?.addOnCompleteListener(OnCompleteListener {
when(it.isSuccessful) {
true -> apply {
Intent(this#LoginActivity, MainActivity::class.java).apply {
startActivity(this)
finish()
}
}
false -> Toast.makeText(this#LoginActivity, "Login has failed", Toast.LENGTH_SHORT).show()
}
})
}
}
After some searching, I found the solution to my problem.
It appears that because I was authenticating users on the client and having a backend that communicated with Firebase's Realtime Database, I had to use Firebase's Admin SDK in the backend.
This is because it was required to pass a unique token generated each time a user logs in and authenticates in the client. This token is then required to be sent to the backend and used when trying to access the Realtime Database.
For anyone else that will stumble upon this question and want to know how it can be done, follow the links below:
Adding Firebase Admin SDK
Verifying ID Tokens
Medium Article Explaining Everything
Also, make sure to reference your database name correctly
It seems a problem with the permission you have given to your node i.e users and try below way
Only authenticated users can access/write data
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}

VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user XXXX1145-8bcb-48d6-b8a8-dcb75955b738

I am getting 'Invalid token' error while Email confirmation in .NET core.
Above error is thrown randomly. Clicking the confirmation link for the first time is throwing error and again if we click on the same link email is getting confirmed.
Web application is deployed in Azure. Also in logs we found the below error
VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user XXXX1145-8bcb-48d6-b8a8-dcb75955b738.
Email Confirmation method is below
public async Task<IActionResult> ConfirmEmail(string userid, string token)
{
ApplicationUser user = await _userManager.FindByIdAsync(userid);
if(user != null)
{
IdentityResult result = await _userManager.ConfirmEmailAsync(user, token);
if (result.Succeeded)
{
return Redirect("/Thankyou?status=confirm");
}
else
{
return Redirect("/Thankyou?status=" + result.Errors.ToArray()[0].Description);
}
}
else
{
return Redirect("/Thankyou?status=Invalid User");
}
}
I had the same problem, I solved it by decoding my URL encoded tokens:
var decodedTokenString = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(token));
It looks like the user account is already confirmed. You can take a look at the value of User.EmailConfirmed.

Clear sessions and old cookies in ASP.Net Core

I have a website with a lot of registered users and many of them have chosen the "remember me" option in login.
I used to use the default login behavior for asp.net core but I installed openiddict and added the following option to services.addIdentity:
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
else
{
context.Response.Redirect(context.RedirectUri);
}
return Task.FromResult(0);
}
};
}
The full method in startup.cs now reads the following:
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequiredLength = 6;
options.Cookies.ApplicationCookie.CookieDomain = "mydomain.com";
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(1);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
else
{
context.Response.Redirect(context.RedirectUri);
}
return Task.FromResult(0);
}
};
The problem now that if a previously registered and logged-in user tried to open pages that require authentication he gets an error message. Unfortunately I'm unable to determine that error because appinsights and "development" mode doesn't work for me in Azure. if users go to login page without logging out they get a blank page after logging in.
The only way to solve it is to logout and login again.
Because I have a lot of users I'm trying to find a way to clear all sessions or previous cookies.
Any suggestions on this or comments about my code above is strongly appreciated.
Thank you
Update: I tried try catch and the error happened. Apparently there is no exception... This is very weird.
Update2: This is not account related. A friend of mine is facing the error and gave me his credentials. When I tried it works, perhaps it's a cookie problem?

Resources