I built a simple app that allows our customers to gather specific information from their Salesforce system. For authentication I used "WebServer Flow", which allows a user to log in to our site with his Salesforce account.
I should of course allow the user to log out of his account. But for some reason, even though I send a Revoke request to Salesforce and get an OK response, when the user redirected again to the Salesforce login page, it automatically logs in to the previous account without re-entering details.
this is the logout action in my backend,
public async Task<ContentResult> LogOutFromSalseforce(string code)
{
AuthenticationClient auth;
bool hasAuth = AuthSessionWrapper.AuthDic.TryGetValue(code, out auth);
if (!hasAuth) return Content(JsonConvert.SerializeObject(new { error = "session expired" }), "application/json");
var url = auth.InstanceUrl + _revokeEndpointUrl;
var cl = new HttpClient();
var res = await cl.PostAsync(url, new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("token", auth.RefreshToken) }));
AuthSessionWrapper.AuthDic.Remove(code);
return Content(JsonConvert.SerializeObject(new { success = res.StatusCode == HttpStatusCode.OK }), "application/json");
}
And after call from client to this action he redirected to our login page.
I found that even if i call to this revoke endpoint from client it's not work.
only if the user enter in another tab to Salesforce and click logout there, he need to re enter his details to login again to our site.
What I'm doing wrong?
If someone get into the same problem, I solved it with add "&prompt=login" to the login redirect url.
Related
In my Blazor WebAssembly, I call the API to fetch some data. The user must be authenticated against the Identity Server. In the header of the request, I add the user token.
In the page, the user has to select some dropdown list and then press the submit button. On the click, the application calls the API with the following function (the result conversion is omitted).
private readonly IAccessTokenProvider _accessToken;
public APIService(HttpClient httpClient, IAccessTokenProvider accessToken)
{
_httpClient = httpClient;
_accessToken = accessToken;
}
public async Task<APIResponse> GetAttributeAsync(APIRequest apirequest)
{
var tokenResult = await _accessToken.RequestAccessToken();
tokenResult.TryGetToken(out var token);
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Post, $"typing");
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(
"Bearer", token.Value);
// ...
return APIResponse;
}
Then, it hides the form and display the result from the API. There is a back button, that hides the result and shows again the form.
The web application is working fine as I expected. Then, I wanted to try the web application on iOS (iPhone or iPad). I fill the form, submit the request and display the data as expected. Then I click the button to display again the form and send another request: when I sent the request, the function above generates an error
Arg_NullReferenceException
If I refresh the page, the web application is working again. The behaviour is consistent in iOS with Safari, Edge and Chrome.
I guess, for some reasons, the RequestAccessToken() is not able the second time to retrieve the user token.
Have someone else had this issue? How can I fix it?
Update
After a day of testing, what I can say is that on Windows the function RequestAccessToken() finds the token every time I ask to retrieve it. On iOS devices, the application can read the token only once and then the token is removed. I don't know if it is correct, but I added a small cache in the Local Storage to save the token and reuse it.
Is it the correct way to approach the problem?
I have a strange error when I work in firebase flutter facebook login.
It always results in null email. And when I see the firebase console, the email field is registering with _.
I have searched on StackOverflow to figure out this error but could not succeed.
And I have followed the steps in facebook account for iOS setup.
What kind of possible reasons are there?
And If I try to log in with facebook, this shows "You previously logged in to this app with facebook account" even though I never logged in before...
Help me guys. I am struggling with this issue for more than 10 days!!!
// Sign in with Facebook.
static Future<Map<String, dynamic>> signInWithFacebook({bool isSignUp}) async {
try {
await signOutFacebook();
UserCredential userCredential;
// Trigger the sign-in flow
List<String> permissions = ['email', 'public_profile'];
final LoginResult loginResult = await FacebookAuth.instance.login(permissions: permissions);
// Create a credential from the access token
final OAuthCredential facebookAuthCredential =
FacebookAuthProvider.credential(loginResult.accessToken.token);
// Once signed in, return the UserCredential
userCredential = await FirebaseAuth.instance.signInWithCredential(facebookAuthCredential);
final User user = userCredential.user;
print("User info after facebook login ${user.providerData[0].email} ${user.uid}");
// ************************************** This is showing null email ***** //
if (isSignUp) {
Map<String, dynamic> resultOfSaveSocialUserToDatabase = await saveSocialUserToDatabase(user, 'facebook');
return resultOfSaveSocialUserToDatabase;
} else {
Map<String, dynamic> resultOfValidateSocialLogin = await validateSocialLogin(user, 'facebook');
return resultOfValidateSocialLogin;
}
} catch (e) {
print(e);
return {'success': false, 'message': "Sign up with social account failed"};
}
}
This happens cause you might have created your facebook account using your phone number instead of email.
So, it turns out to be an empty email address as an empty identifier.
You can try out with a different fb account which may be created using an email address instead of phone number.
This can also happen when the user elects to not share his email when login in with his FB account for the first time.
I have created webhook project with Microsoft Graph API to monitor Office 365 inbox.
I made a UpdateSubscription action method which renews it for 3 days only as according to the documentation provide on https://graph.microsoft.io/en-us/docs/api-reference/v1.0/resources/subscription
Below is the code snippet of how I'am facilitating the HTTP request to update the subscription
AuthenticationResult authResult = await AuthHelper.GetAccessTokenAsync();
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Build the request.
string subscriptionsEndpoint = "https://graph.microsoft.com/v1.0/subscriptions/"+id;
var method = new HttpMethod("PATCH");
HttpRequestMessage request = new HttpRequestMessage(method, subscriptionsEndpoint);
//get the current time
var subscription = new Subscription
{
//Id = id,
ExpirationDateTime = DateTime.UtcNow + new TimeSpan(0, 0, 4230, 0)
};
Is there a way to auto update without the user pressing the button to 'update'?
since the authorization-headers requires AuthResult.accessToken which will require the user to sign in to Office365 account.
Please advice
An option available to you is the service or daemon approach (https://graph.microsoft.io/en-us/docs/authorization/app_only). Instead of authenticating with a logged-in user you're able to renew the subscription at the application level using a Bearer token which is in turn generated by the CLIENT_SECRET from Azure AD.
I don't think storing tokens in the database is the right approach here. My understanding is that security tokens are never appropriate for a database.
In fact, I don't quite understand the need to have the user log in at all here, unless there are parts to the program that you didn't mention. A service like the one I mentioned can monitor a mailbox without a user being there, or else if the program requires the user to be there, there really isn't an issue of lost credentials.
You can use this approach to fetch accesstoken from azure using grant_type a password. PLease find the below screenshot.
When a user launches the app they are an unauthenticated user and they receive a unauthenticated cognito identity supplied from the DeveloperAuthenticatedIdentityProvider class in the iOS app. I can see that unauthenticated cognito identity in the cognito console. However, when they login and I make a call to my nodejs backend with a logins map of:
{
DevAuthIdentityLogin:<username>
}
and using this backend code:
getCognitoIdentity: function(logins, cognitoId, error) {
var cognitoidentity = new AWS.CognitoIdentity(awsOptions);
var params = {
IdentityPoolId: identityPool,
Logins: logins,
TokenDuration: (60 * 5)
};
cognitoidentity.getOpenIdTokenForDeveloperIdentity(params, function(err, data) {
if (err) {
console.log(err, err.stack);
error(err)
} else {
console.log(data); // successful response
cognitoId(data);
}
});
}
It creates a new identity id with the developer authenticated identity and I can see that in the cognito console, but the old unauthenticated one is not being mapped to this new developer authenticated one.
Do I need to supply the unauthenticated identity id in the logins map when making a call to my backend to associate the two? OR am I not making this call correctly. I need some clarification on how to map/merge these identities please.
I already answered your question on our forums, but you need to include the unauth identitity id as a parameter to the GetOpenIdTokenForDeveloperIdentity call, otherwise Amazon Cognito will have no way of knowing that it should associate your user identifier to that identity.
When a user is redirected to Google to login, but then clicks 'Cancel' when granting permissions, I get the following error in my OpenIDAuthenticationFilter:
"No claimed identity supplied in authentication request"
and in my handler:
OpenIDAuthenticationFailureHandler org.springframework.security.authentication.AuthenticationServiceException: Unable to process claimed identity ''
How can I properly catch this, knowing that the user denied requested permissions?
In fact , I fixed the problem,
first detect Referer:
if (request.getHeader("Referer") != null
&& request.getHeader("Referer").startsWith(myOpenIdServerURL)) {
if it is in, it means openId server reject your request, then redirect to login page with error code:
...
redirectUrl = redirectUrl + "?error=access_denied";
return new ModelAndView("redirect:" + redirectUrl, model);