IdentityServer4.Validation.TokenRequestValidator: Invalid authorization code - identityserver4

I am using Identity Server 4 With Microsoft Blazor application. Authentication process works fine in local. But after deploying changes in azure it was working fine before one week. Suddenly it's started giving some errors and stuck on https://websiteurl.com/signin-oidc page. After checking identity server log I found this error
IdentityServer4.Validation.TokenRequestValidator: Invalid authorization code
Some times it's working and some times getting above error. More than 50% of time i am getting above error.
I tried following code generate custom codeVerifier and add before redirecting to identity server.
if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
{
// generate code_verifier
var codeVerifier = CryptoRandom.CreateUniqueId(32);
// store codeVerifier for later use
context.Properties.Items.Remove(CODE_VERIFIER_KEY);
context.Properties.Items.Add(CODE_VERIFIER_KEY, codeVerifier);
Logger.Log(LogLevel.Information, CODE_VERIFIER_KEY + ": " + codeVerifier);
// create code_challenge
string codeChallenge;
using (var sha256 = SHA256.Create())
{
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64Url.Encode(challengeBytes);
}
// add code_challenge and code_challenge_method to request
context.ProtocolMessage.Parameters.Remove(CODE_CHALLENGE_KEY);
context.ProtocolMessage.Parameters.Remove(CODE_CHALLENGE_METHOD_KEY);
Logger.Log(LogLevel.Information, CODE_CHALLENGE_KEY + ": " + codeChallenge);
context.ProtocolMessage.Parameters.Add(CODE_CHALLENGE_KEY, codeChallenge);
context.ProtocolMessage.Parameters.Add(CODE_CHALLENGE_METHOD_KEY, "S256");
}
OnAuthorizationCodeReceived = (context) =>
{
// context.Options.
//Add claim if they are
//var claims = new List<Claim> { new Claim(ClaimTypes.Role, "Provider") };
//var appIdentity = new ClaimsIdentity(claims);
//context.Principal.AddIdentity(appIdentity);
// only when authorization code is being swapped for tokens
// only when authorization code is being swapped for tokens
Logger.Log(LogLevel.Information, "OnAuthorizationCodeReceived - " + context.TokenEndpointRequest.Parameters);
if (context.TokenEndpointRequest?.GrantType == OpenIdConnectGrantTypes.AuthorizationCode)
{
// get stored code_verifier, This if condition is never gets executed
if (context.Properties.Items.TryGetValue(CODE_VERIFIER_KEY, out var codeVerifier))
{
// add code_verifier to token request
context.TokenEndpointRequest.Parameters.Add(CODE_VERIFIER_KEY, codeVerifier);
}
}
return Task.CompletedTask;
},

Related

Multiple entries on DbUpdateException when one is expected

I sync data from an api and detect if an insert or update is necessary.
From time to time I receive DbUpdateExceptions and then fallback to single insert/update + savechanges instead of addrange/updaterange + savechanges.
Because single entities are so slow I wanted to only remove the failing entity from changetracking and try to save it all again, but unfortunately mssql returns all entities instead of only the one that is failing in DbUpdateException.Entries.
Intellisense tells me
Gets the entries that were involved in the error. Typically this is a single entry, but in some cases it may be zero or multiple entries.
Interestingly this is true if I try it on a mysql server. There only one entity is returned, but mssql returns all, which makes it impossible for me to exclude only the failing one.
Is there any setting to change mssql behaviour?
Both mysql and mssql are azure hosted resources.
Here an example:
var addList = new List<MyEntity>();
var updateList = new List<MyEntity>();
//load existing data from db
var existingData = Context.Set<MyEntity>()
.AsNoTracking()
.Take(2).ToList();
if (existingData.Count < 2)
return;
//addList
addList.Add(new MyEntity
{
NotNullableProperty = "Value",
RequiredField1 = Guid.Empty,
RequiredField2 = Guid.Empty,
});
addList.Add(new MyEntity
{
NotNullableProperty = "Value",
RequiredField1 = Guid.Empty,
RequiredField2 = Guid.Empty,
});
addList.Add(existingData.ElementAt(0)); //this should fail due to duplicate key
addList.Add(new MyEntity
{
NotNullableProperty = "Value",
RequiredField1 = Guid.Empty,
RequiredField2 = Guid.Empty,
});
//updateList
existingData.ElementAt(1).NotNullableProperty = null; //this should fail due to invalid value
updateList.Add(existingData.ElementAt(1));
//save a new entity that should fail
var newKb = new MyEntity
{
NotNullableProperty = "Value",
RequiredField1 = Guid.Empty,
RequiredField2 = Guid.Empty,
};
Context.Add(newKb);
Context.SaveChanges();
newKb.NotNullableProperty = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"; //this should fail due to length
updateList.Add(newKb);
try
{
if (addList.IsNotNullOrEmpty())
context.Set<MyEntity>().AddRange(addList);
if (updateList.IsNotNullOrEmpty())
context.Set<MyEntity>().UpdateRange(updateList);
context.SaveChanges();
}
catch (DbUpdateException updateException)
{
//updateException.Entries contains all entries, that were added/updated although only three should fail
}

Gatling2 Failing to use user session properly

I hope someone can point me into the right direction!
I try to run one scenario which has several steps that have to be executed in order and each with the same user session to work properly. The below code works fine with one user but fails if I use 2 or more users...
What am I doing wrong?
val headers = Map(
Constants.TENANT_HEADER -> tenant
)
val httpConf = http
.baseURL(baseUrl)
.headers(headers)
val scen = scenario("Default Order Process Perf Test")
.exec(OAuth.getOAuthToken(clientId))
.exec(session => OAuth.createAuthHHeader(session, clientId))
.exec(RegisterCustomer.registerCustomer(customerMail, customerPassword,
tenant))
.exec(SSO.doLogin(clientId, customerMail, customerPassword, tenant))
.exec(session => OAuth.upDateAuthToken(session, clientId))
.exec(session =>
UpdateCustomerBillingAddr.prepareBillingAddrRequestBody(session))
.exec(UpdateCustomerBillingAddr.updateCustomerBillingAddr(tenant))
.exec(RegisterSepa.startRegisterProcess(tenant))
.exec(session => RegisterSepa.prepareRegisterRequestBody(session))
.exec(RegisterSepa.doRegisterSepa(tenant))
setUp(
scen
.inject(atOnceUsers(2))
.protocols(httpConf))
object OAuth {
private val OBJECT_MAPPER = new ObjectMapper()
def getOAuthToken(clientId: String) = {
val authCode = PropertyUtil.getAuthCode
val encryptedAuthCode = new
Crypto().rsaServerKeyEncrypt(authCode)
http("oauthTokenRequest")
.post("/oauth/token")
.formParam("refresh_token", "")
.formParam("code", encryptedAuthCode)
.formParam("grant_type", "authorization_code")
.formParam("client_id", clientId)
.check(jsonPath("$").saveAs("oauthToken"))
.check(status.is(200))
}
def createAuthHHeader(session: Session, clientId: String) = {
val tokenString = session.get("oauthToken").as[String]
val tokenDto = OBJECT_MAPPER.readValue(tokenString,
classOf[TokenDto])
val session2 = session.set(Constants.TOKEN_DTO_KEY, tokenDto)
val authHeader = AuthCommons.createAuthHeader(tokenDto,
clientId, new util.HashMap[String, String]())
session2.set(Constants.AUTH_HEADER_KEY, authHeader)
}
def upDateAuthToken(session: Session, clientId: String) = {
val ssoToken = session.get(Constants.SSO_TOKEN_KEY).as[String]
val oAuthDto = session.get(Constants.TOKEN_DTO_KEY).as[TokenDto]
val params = new util.HashMap[String, String]
params.put("sso_token", ssoToken)
val updatedAuthHeader = AuthCommons.createAuthHeader(oAuthDto,
clientId, params)
session.set(Constants.AUTH_HEADER_KEY, updatedAuthHeader)
}
}
def createAuthHHeader(session: Session, clientId: String) = {
val tokenString = session.get("oauthToken").as[String]
val tokenDto = OBJECT_MAPPER.readValue(tokenString,
classOf[TokenDto])
val session2 = session.set(Constants.TOKEN_DTO_KEY, tokenDto)
val authHeader = AuthCommons.createAuthHeader(tokenDto,
clientId, new util.HashMap[String, String]())
session2.set(Constants.AUTH_HEADER_KEY, authHeader)
}
So I did add the two methods that dont work along as expected. In the first part I try to fetch a token and store in the session via check(jsonPath("$").saveAs("oauthToken")) and in the second call I try to read that token with val tokenString = session.get("oauthToken").as[String] which fails with the exception saying that there is no entry for that key in the session...
I've copied it and removed/mocked any missing code references, switched to one of my apps auth url and it seems to work - at least 2 firsts steps.
One thing that seems weird is jsonPath("$").saveAs("oauthToken") which saves whole json (not single field) as attribute, is it really what you want to do? And are you sure that getOAuthToken is working properly?
You said that it works for 1 user but fails for 2. Aren't there any more errors? For debug I suggest changing logging level to TRACE or add exec(session => {println(session); session}) before second step to verify if token is properly saved to session. I think that something is wrong with authorization request (or building that request) and somehow it fails or throws some exception. I would comment out all steps except 1st and focus on checking if that first request is properly executed and if it adds proper attribute to session.
I think your brackets are not set correctly. Change them to this:
setUp(
scn.inject(atOnceUsers(2))
).protocols(httpConf)

Google Identity Toolkit Java library's gitkitClient.getAllUsers() doesn't work correctly

I have been trying to get all the users for my web application (GAE for Java backend) using gitkitClient.getAllUsers(). I'm just getting started with Identity Toolkit and have 10-12 users.
When I call gitkitClient.getAllUsers() it doesn't find any user and returns this warning:
com.google.identitytoolkit.GitkitClient$1 getNextResults
WARNING: JSONObject["email"] not found.
If I call it with a parameter for max results gitkitClient.getAllUsers(5), it returns 5 users correctly. But if I pass 7, it again doesn't find any user, and returns the same warning (as above). I know that I have 10+ users.
If I use gitkitClient.getUserByEmail("test#example.com") I can get the users that are not returned in the first 5.
Here's my code sample:
Iterator<GitkitUser> allUsers = gitkitClient.getAllUsers();
int count = 0;
if (allUsers != null) {
while (allUsers.hasNext()) {
count++;
GitkitUser gUser = allUsers.next();
logger.info("" + count + ". User email : " + gUser.getEmail() + " Id : " + gUser.getLocalId());
}
}
Am I missing something?
Are you using the iterator like this:
val userIterator = gitkitClient.getAllUsers();
while (userIterator.hasNext()) {
LOG.warning(userIterator.next().getEmail)
}
I've not been keeping to close an eye on the number of users, but this seems to return ALL of the known users.
B.

Symfony 2 - WSSE - FOSUserBundle - FOSRestBundle - Javascript

I try to incorporate WSSE Authentification. I have a symfony in back, and an app Ionic - AngularJS in front.
I followed the cookbook about WSSE, and theses tutorials :
http://obtao.com/blog/2013/05/create-rest-api-in-a-symfony-application/
http://obtao.com/blog/2013/06/configure-wsse-on-symfony-with-fosrestbundle/
And
http://obtao.com/blog/2013/09/how-to-use-wsse-in-android-app/
I install WSSE well, i can hash my password in my app with this code:
authentication.hashPassword = function(salt, clearPassword) {
var digest = "";
console.log('==== STARTING HASHING PASSWORD ====');
var salted = null;
if (!salt || salt == "") {
salted = clearPassword;
} else {
salted = clearPassword + "{" + salt + "}";
}
digest = CryptoJS.SHA512(salted);
for (var i=1; i<5000; i++) {
digest = CryptoJS.SHA512(digest.toString(CryptoJS.enc.Latin1)+salted);
}
digest = digest.toString(CryptoJS.enc.Base64);
console.log('==== ENDING HASHING PASSWORD ====');
console.log(digest);
return digest;
};
but i would like to generate header with my hash password ( the last tutorial is coded in java, and i'm a noob in Java)
Is it Possible to compare two hash password if i post my hash password ?
have you any idea to create a header ( or Token ) ?
Thank you for your answer
Your application seems to be based on Ionic Framework. After the "Android application" mentioned in tutorial, we have also tested ionic.
See https://github.com/wallabag/ionic-app (crypto is "handmade", but it will help you for the header part with ionic/angularjs)
In app.js :
$http.defaults.headers.common['x-wsse'] = function() {
return wsse.getHeaderValue(username, encryptedPassword);
};
$http.defaults.headers.common.Authorization = 'profile=UsernameToken';

oauth problem( app engine)

i am trying to pull user's documents data from google docs using oauth,
but i cannot understand how to do it
- what's the purpose of oauth_verifier
- how to get the access token secret?
- if i try to use DocsService below, then i have a "server error"
- is there a clear tutorial for this? i cannot find any atm..
String oauth_verifier = req.getParameter("oauth_verifier");
String oauth_token = req.getParameter("oauth_token");
String oauthtokensecret = req.getParameter("oauth_token_secret");
GoogleOAuthParameters oauthparam = new GoogleOAuthParameters();
oauthparam.setOAuthConsumerKey("consumer key");
oauthparam.setOAuthConsumerSecret("secret");
oauthparam.setOAuthToken(oauth_token);
oauthparam.setOAuthTokenSecret(oauthtokensecret);
oauthparam.setOAuthVerifier(oauth_verifier);
OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();
GoogleOAuthHelper oauthhelper = new GoogleOAuthHelper(signer);
String accesstoken = "";
String accesstokensecret = "";
try {
oauthhelper.getUnauthorizedRequestToken(oauthparam);
accesstoken = oauthhelper.getAccessToken(oauthparam);
accesstokensecret = oauthparam.getOAuthTokenSecret();
// DocsService client = new DocsService("yourCompany-YourAppName-v1");
...
These may not be what you are looking for, since they are OAuth-specific and not google-related, but I found these "Getting started" articles very helpful:
http://oauth.net/documentation/getting-started
Turns out that I need to get the oauth_token_secret and reuse it later.
So (before redirecting user to google login page)
oauthhelper.getUnauthorizedRequestToken(oauthparam);
requesturl = oauthhelper.createUserAuthorizationUrl(oauthparam);
OAuthTokenSecret.tokenSecret = oauthparam.getOAuthTokenSecret();
resp.sendRedirect(requesturl);
Then after the user grants access and we have been redirected to oauth_callback url:
oauthparam.setOAuthToken(oauthtoken);
oauthparam.setOAuthVerifier(oauthverifier);
oauthparam.setOAuthTokenSecret(OAuthTokenSecret.tokenSecret);
oauthhelper.getAccessToken(oauthparam); // access token and access token secret are saved in oauthparam.
// access google service..
GoogleService googleService = new GoogleService( "cp", "test222");
googleService.setOAuthCredentials(oauthparam, signer);
BaseFeed resultFeed = googleService.getFeed(feedUrl, Feed.class);

Resources