There is no pending identity provider logout request - adfs

I'm using ComponentSpace for SSO which is working fine, but it gives error when I try to SendSLO from the SP, where SLO is initiated by the ADFS server (IdP).
The code:
bool isRequest = false;
string logoutReason = null;
string partnerSP = null;
try
{
ComponentSpace.SAML2.SAMLServiceProvider.ReceiveSLO(Request, out isRequest, out logoutReason, out partnerSP);
}
catch (SAMLProtocolException ex)
{
if (ex.Message != "A logout response was unexpectedly received.") //Multiple SLOs can be sent on each logout
CommonRepository.LogException(ex.Message, ex, "SAML logout error");
}
catch (Exception ex)
{
CommonRepository.LogException(ex.Message, ex, "SAML logout error");
}
if (isRequest) {
// Logout locally.
FormsAuthentication.SignOut();
// Respond to the IdP-initiated SLO request indicating successful logout.
ComponentSpace.SAML2.SAMLServiceProvider.SendSLO(Response, null); // Fails at this point
} else {
// SP-initiated SLO has completed.
//FormsAuthentication.RedirectToLoginPage();
// This will log out the user from Communifire Application
Utilities.LogoutWithoutRedirect();
.....
}
When IdP initiates SLO, first I call ReceiveSLO, then logout from the service provider, at last call SendSLO, but it throws
ComponentSpace.SAML2.Exceptions.SAMLProtocolException: 'There is no pending identity provider logout request.'
How can I fix this? If I call IsSendSLOPending, it returns false, why is that?
Thank you.

Related

Unable to consume a webapi from link in an email

I'm testing a webapi that sends email with a link for user verification, I receive the email, but when I click the link, it does not verify the user via the email link, instead I get the below error
No webpage was found for the web address: http://localhost:4000/account/verify-email?token={token}
see below code in controller for the verification
[HttpPost("verify-email")]
public IActionResult VerifyEmail(VerifyEmailRequest model)
{
_accountService.VerifyEmail(model.Token);
return Ok(new { message = "Verification successful, you can now login" });
}
see code in services class
public void VerifyEmail(string token)
{
var account = _context.Accounts.SingleOrDefault(x => x.VerificationToken == token);
if (account == null) throw new AppException("Verification failed");
account.Verified = DateTime.UtcNow;
account.VerificationToken = null;
_context.Accounts.Update(account);
_context.SaveChanges();
}
Code true working,
You need check http://localhost:4000/account/verify-email?token={token} url.
You send this url. Your project working in Localhost:4000?
Make sure you have:
[Route("account")]
At the top

FCM throws 401 after some time for data message notification

I am sending data message notification from Java app server to the FCM rest endpoint. Everything works fine, data messages are received by the app without any issues, however after some time (without any noticeable trend) , FCM stars returning 401. I am using Apache common's HTTPClient library to make the http callss. This is the relevant code snippet
final HttpPost httpPost = new HttpPost("https://fcm.googleapis.com/v1/projects/proj1/messages:send");
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Authorization", "Bearer "+ accessToken);
responseBody = httpclient.execute(httpPost, responseHandler);
And this snippet is for getting the access token for API authorization
static{
FileInputStream refreshToken = null;
refreshToken = new FileInputStream("C:/prj/proserviceaccoutkey.json");
googleCredentials=GoogleCredentials.fromStream(refreshToken).createScoped("https://www.googleapis.com/auth/firebase.messaging");
options = new FirebaseOptions.Builder() .setCredentials(googleCredentials).build();
}
// Gets called each time a data message needs to be sent
public static synchronized String getAccessToken()
{
if(googleCredentials.getAccessToken()==null)
try {
googleCredentials.refresh();
} catch (IOException e) {
e.printStackTrace();
}
return googleCredentials.getAccessToken().getTokenValue();
}
looks like googleCredentials.getAccessToken() will always return non-null, even when the cahce token in no longer valid, and this is why token was not getting refreshed in the code. Applied the following fix, and it's working now.
public static synchronized String getAccessToken()
{
if(googleCredentials!=null)
try {
googleCredentials.refresh();
} catch (IOException e) {
e.printStackTrace();
}
return googleCredentials.getAccessToken().getTokenValue();
}
Though, it's not really utilizing the cached token, as every time it will be refreshing the token, but my issue has been rsolved for now.

Site redirects to /Login method after successfull authentication

Im developing an MVC 5.0 .ASP NET app. Im using Identity to authorize users. I've added another method to AccountController where user can log in with Token. After 'signing in' in my method instead of rendering chosen view application redirects to default login method. When you type mysite/home/ it shows that user is logged in.
I can't find when the redirect to Login is made.
Any ideas how to fix this?
To authenticate user in my action I use this method:
private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
My custom login action
[AllowAnonymous]
public async Task<ActionResult> LoginWithToken(string token, string returnUrl)
{
AccountService accountService = new AccountService(db);
string userId;
try
{
userId = await accountService.GetUserIdFromToken(token);
}
catch (Exception exception)
{
ModelState.AddModelError(exception.Message, exception);
return RedirectToAction("Login");
}
var user = await UserManager.FindByIdAsync(userId);
try
{
await SignInAsync(user, false);
}
catch (Exception)
{
ModelState.AddModelError("Logowanie nieudane. Konto mogło zostać zablokowane lub usunięte. Skontaktuj się z administratorem serwisu.", new AccessViolationException());
return RedirectToAction("Login");
}
LogUserLogin(user.UserName, Request.UserHostAddress);
string decodedUrl = "";
if (!string.IsNullOrEmpty(returnUrl))
decodedUrl = Server.UrlDecode(returnUrl);
if (Url.IsLocalUrl(decodedUrl))
{
return View((object)decodedUrl);
}
else
{
return RedirectToAction("Home", "Index", new { });
}
}
EDIT:
I've found out that when my method is hitting return View((object)decodedUrl); request doesn't contains ".AspNet.ApplicationCookie". I've set breakpoint on Application_BeginRequest and right after renturn View((object)decodedUrl) there is request to Login action. At this point there is ".AspNet.ApplicationCookie" in request.
Finally I've found that the authentication cookie wasn't set to the current request but to next request.
Now my LoginWithToken Method redirects to another [AllowAnonymous] Action so the cookie is set. Then that action redirects to authorisation restricted areas.

Authentication and Authentication Header in OkHTTP

I am facing a rather simple situation but I cannot wrap my head around it. Maybe the OkHttp gurus could light my path.
I am using Picasso, Retrofit and OkHttp for multiple purposes on my android app. yay!. As I read properly, the developer should make an effort in keeping on OkHttpClient (as read here ).
With the approach in mind, I want any of my HTTP calls (be it an API call, an Image loading, a resource download) to :
Send the request
If HTTP401 is received, then Send another HTTP Request that sends a token back
When that token is received, the call is re-emitted with that token included in the headers
Any subsequent call (be it an API, a resource or image call) should use that token until the next HTTP401 is received (invalid token).
Of course, I would reuse the same client for Retrofit and Picasso.
One route I am considering is to use a mix of Authenticator and an application Interceptor. Authenticator should catch HTTP401, but can I make it make another sync request in the meantime, store the token and activate the new interceptor ?
Looks like I found the solution myself to that problem so let's share the knowledge to everyone.
In order to this, OkHttp already gives all the necessary hooks.
Make sure to use Authenticator
Install an interceptor once the authenticator succeed
Return a request with the good token.
This also imply that the Authenticator handles an HTTP to set your token back (done in another android service).
okHttpClient.setAuthenticator(new Authenticator() {
#Override
public Request authenticate(Proxy proxy, Response response) {
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Authenticator.ACCOUNT_TYPE);
// No account, do not even try to authenticate
if (accounts.length == 0) {
Log.i(TAG, "... But we dont have any account yet, so I will just back off for now.");
return null;
}
Account account = accounts[0];
try {
final String mCurrentToken = accountManager.blockingGetAuthToken(account, "", false);
// For now, we just re-install blindly an interceptor
okHttpClient.interceptors().clear();
Log.i(TAG, "... Installing interceptor after authentication");
okHttpClient.interceptors().add(new Interceptor() {
#Override public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request newReq = request.newBuilder()
.addHeader("Authorization", mCurrentToken)
.build();
Response response = chain.proceed(newReq);
return response;
}
});
Log.i(TAG, "Install temporary auth token in request");
return response.request().newBuilder()
.addHeader("Authorization", mCurrentToken)
.build();
} catch (OperationCanceledException e) {
Log.e(TAG, "Interrupted exception");
return null;
} catch (AuthenticatorException e) {
Log.e(TAG, "Authentication error");
return null;
} catch (IOException e) {
Log.e(TAG, "IO Error");
return null;
}
}
#Override
public Request authenticateProxy(Proxy proxy, Response response) {
return null; // Null indicates no attempt to authenticate.
}
})
With this, just use this OkClient in Picasso and Retrofit.

how to check for authentication of users login in custom application using CMIS in alfresco?

I have made custom webapp using CMIS with which I am able to get the document from repository of alfresco and also able to upload document from my webapp into the repository of alfresco. But it is not checking for user authentication, if I try to login with random user who doesn't have access to the alfresco repository he/she is also able to login.
I am using below code:
public Session getSession() {
Properties prop = new Properties();
try {
prop.load(getClass().getClassLoader().getResourceAsStream("config.properties"));
ALFRSCO_ATOMPUB_URL = "http://" + prop.getProperty("url") + ":"
+ prop.getProperty("port") + "/alfresco/service/cmis";
System.out.println(ALFRSCO_ATOMPUB_URL);
parameter.put(SessionParameter.USER, prop.getProperty("USER"));
parameter.put(SessionParameter.PASSWORD,
prop.getProperty("PASSWORD"));
// Specify the connection settings
parameter.put(SessionParameter.ATOMPUB_URL, ALFRSCO_ATOMPUB_URL);
parameter.put(SessionParameter.BINDING_TYPE,
BindingType.ATOMPUB.value());
parameter.put(SessionParameter.REPOSITORY_ID,
prop.getProperty("REPOSITORY_ID"));
SessionFactory factory = SessionFactoryImpl.newInstance();
session = factory.getRepositories(parameter).get(0).createSession();
return session;
} catch (CmisUnauthorizedException ex) {
System.out.println("you are unauthorized ");
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
return session;
}
public boolean validateUser() {
Session session = getSession();
System.out.println("session " + session);
if (session != null) {
FolderBean.cmisSession = session;
return true;
}
return false;
}
Any advice would be appreciated!!!
You are reading username and password from config.properties file.You should change that with the username and password which are entered in your webapp.
Below line in your code reads property file.
prop.load(getClass().getClassLoader().getResourceAsStream("config.properties"));
Below is reading username and password from property file.
parameter.put(SessionParameter.USER, prop.getProperty("USER"));
parameter.put(SessionParameter.PASSWORD,prop.getProperty("PASSWORD"));
Instead of that put here username and password of webapp which you are entering.

Resources