OAuth2 authentication with an CSRF-Token in Flutter - cookies

I want to authenticate my flutter app to an REST API with the Oauth2 package but the REST API ask the CSRF Token in the request. Here is my code, does someone know how and where I can add this Token ?
I tried to modify the example of code provide by Oauth2 flutter library, but it doesn't work.
void Login() async {
final authorizationEndpoint = Uri.parse(
"http://ipadress:8000/oauth2/authorization/");
final username = "user";
final password = "pass";
final identifier = "DG9GSrfae8gCzWDJU0jbxQC6DAUsTl8dSBMxwPEz";
final secret = await getCsrftoken();
var client = await oauth2.resourceOwnerPasswordGrant(
authorizationEndpoint, username, password,
identifier: identifier, secret: secret,);
var result = await client.read("http://ipadress/api/users/me/");
print(result);
new File("~/.myapp/credentials.json")
.writeAsString(client.credentials.toJson());
}
Future<String> getCsrftoken() async {
var response =
await http.get(Uri.encodeFull('http://ipadress:8000/login/'));
var csrftoken =
response.headers.remove('set-cookie').substring(10, 74); //csrf 64 chars
return csrftoken;
}
$ Forbidden (CSRF cookie not set.): /oauth2/authorization/
$ "POST /oauth2/authorization/ HTTP/1.1" 403 2990

Related

Set identity cookie in axios

I have setup a project with core identity and successfully register users via my endpoint but I am unable to get the claims principal to my client browser.
using postman to make a post:
https://localhost:7273/signin?username=test&password=Test123!
I can then do the following get in postman
https://localhost:7273/getuserinfo
To successfully get my userclaims from the cookie and retrieve the userinfo.
However when I do the same requests in my nuxt application with axios no cookie is ever set and my response.headers is undefined.
const res = await this.$axios.$post("https://localhost:7273/signin", {}, { params : {username : "test", password: "Test123!"}},
{withCredentials: true}).then(function(response) {
console.log({ headers: response.headers
});
});
In my backend I get signinResult = succeeded
[Route("Signin")]
[HttpPost]
public async Task<IActionResult> Signin(string username, string password)
{
var signinResult = await _signinManager.PasswordSignInAsync(username, password, true, false);
var principal = HttpContext.User as ClaimsPrincipal;
return Ok();
}
What link am I missing that is making this work in postman but not in my webapp?

Firebase OAuthProvider oidc (keycloak) invalid nonce

Here using keycloak to get idToken
Getting error when using signInWithCredential in firebase
Error
The nonce in ID Token "68963ae6-e032-42b4-a7b1-5672f053acf5" does not match the SHA256 hash of the raw nonce "68963ae6-e032-42b4-a7b1-5672f053acf5" in the request.
const provider = new OAuthProvider('oidc.inspect-app');
const auth = getAuth();
const credential = provider.credential({idToken:orginApp.idToken, rawNonce:
orginApp.tokenParsed.nonce});
signInWithCredential(auth, credential)
.then((result:any) => {
//code logic
})
})
I had to switch to code flow to make it work.
In this example i used ionic and OAuth2Client (Capacitor Plugin) to retrieve credentials after native signIn for ios and android.
public async signIn() {
// Ionic Capacitor Plugin
const result = await OAuth2Client.authenticate(OAUTH_OPTIONS);
const provider = new OAuthProvider('oidc.your-keycloak-provider');
provider.addScope('email');
provider.addScope('profile');
provider.addScope('openid');
const credential = provider.credential({
accessToken: result.access_token_response['access_token'],
idToken: result.access_token_response['id_token']
});
return signInWithCredential(this.auth, credential);
}

Google Cloud Function with Basic Auth not working properly

React Client Code - Using request promises to send username and password in Header
var password = values.password;
var email = values.email;
request
.head(
"https://us-central1-simplineet-754e8.cloudfunctions.net/CreateUserAuth"
)
.set('Content-Type', 'application/x-www-form-urlencoded')
.auth(email, password, false)
.query(dataobj)
.then(res => {
console.log(res);
if (res.statusCode === 200) {
console.log("statusText",res.body);
} else {
console.log("statusText",res.statusText);
}
})
.catch(err => {});
Backend - Google Cloud Function to Handle Basic Auth Requests from Client
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({origin: true}));
exports.CreateUserAuth = functions.https.onRequest((request, response) => {
var corsFn = cors();
corsFn(request, response, function () {
// Request Header
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
response.setHeader('Access-Control-Allow-Credentials', true);
response.setHeader('Access-Control-Allow-Origin', '*');
var auth = require('basic-auth') // basic-auth NPM package to extract username and password from header
var user = auth(request)
var email = user.name; // Getting username from Auth
var password = user.pass; // Getting password from Auth
var username = request.query.username;
response.send('Hello from Firebase!'); // Not getting this response in Client
});
});
Response Getting in Client :
Response {req: Request, xhr: XMLHttpRequest, text: null, statusText: "", statusCode: 200, …}
As per MDN docs, HEAD responses should not have a body:
The HTTP HEAD method requests the headers that are returned if the specified resource would be requested with an HTTP GET method. Such a request can be done before deciding to download a large resource to save bandwidth, for example.
A response to a HEAD method should not have a body. If so, it must be ignored. Even so, entity headers describing the content of the body, like Content-Length may be included in the response. They don't relate to the body of the HEAD response, which should be empty, but to the body of similar request using the GET method would have returned as a response.
My guess is that GCP is handling it as a GET and stripping out the body before returning a response.
However, keep in mind that Google Cloud Functions HTTP trigger docs don't explicitly say that HEAD is a supported method:
You can invoke Cloud Functions with an HTTP request using the POST, PUT, GET, DELETE, and OPTIONS HTTP methods.
It looks like you are making a HEAD request instead of a POST request. Change to request.post() and it should work

AWS cognito forgot password flow

I've created an AWS cognito user pool with email as required attribute and checked email for verification. The users are created from my java spring backend service using AWSCognitoClient sdk and calling adminCreateUser(createUser) method. The user gets an email with temporary password, which on signing in for the first time will set new password. Now when I execute the forgot password flow, I get the following error,
InvalidParameterException: Cannot reset password for the user as there is no registered/verified email or phone_number
Although I have received a temporary password to the email id I signed up for and changed my password for very first time I get the above error. Can someone explain what am I missing?
Below is the javascript code am executing for forgot password flow,
forgotPassword(username: String, poolInfo:any){
var poolData = {
UserPoolId : poolInfo.poolId, // Your user pool id here
ClientId : poolInfo.portalClientId // Your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : username,
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.forgotPassword({
onSuccess: function (result) {
this.router.navigate(['login']);
},
onFailure: function(err) {
alert(err);
},
//Optional automatic callback
inputVerificationCode: function(data) {
var verificationCode = prompt('Please input verification code ' ,'');
var newPassword = prompt('Enter new password ' ,'');
cognitoUser.confirmPassword(verificationCode, newPassword, this);
}
});
}
Resolved. I had to add "email_verified":"True" as an attribute for the users I created from my backend service.
I solved this issue with python:
response = cognito_client.get_user_attribute_verification_code(AccessToken='eyJraWQiOiJtTEM4Vm......',AttributeName='email')
response = cognito_client.verify_user_attribute( AccessToken='eyJraWQiOiJtTEM......', AttributeName='email', Code='230433')
def forgot_password(usename):
ClientId = 'f2va............'
response = cognito_client.forgot_password( ClientId=ClientId, Username=username)
def confirm_forgot_password():
ClientId = 'f2va............'
response = cognito_client.confirm_forgot_password(ClientId=ClientId,Username=username,ConfirmationCode='644603',Password='12345678')
Here is the Official Documentation.
https://boto3.amazonaws.com/v1/documentation/api/1.9.42/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.confirm_forgot_password

Facebook Javascript SDK extend access token get "Invalid OAuth access token" - 190 - "OAuthException"

I try to use javacript SDK to get access token and then extend that access token for 60 day. I got reponse error like this from response: Object { message="Invalid OAuth access token.", type="OAuthException", code=190}
My expectation:
Get new access token with 60 days expire
Console to screen.
My Code:
window.onload = function() {
var isLogin = true;
FB.init({appId:422642254433770, cookie:true, status:true, xfbml:true });
FB.getLoginStatus(function(response) {
if (response.status === 'connected') {
// the user is logged in and connected to your
// app, and response.authResponse supplies
// the user’s ID, a valid access token, a signed
// request, and the time the access token
// and signed request each expire
var uid = response.authResponse.userID;
var accessToken = response.authResponse.accessToken;
var accessTokenOld = response.authResponse.accessToken;
//Extend access token
var OauthParams = {};
OauthParams['client_id'] = '//REMOVED APP ID';
OauthParams['client_secret'] = '//REMOVED APP SECRET';
OauthParams['grant_type'] = 'fb_exchange_token';
OauthParams['fb_exchange_token'] = 'accessToken';
OauthParams['response_type'] = 'token';
console.log("Old accessToken => " + accessToken);
FB.api('/oauth/access_token', 'post', OauthParams, function(response) {
console.log(response);
if (!response || response.error) {
console.log(response.accesstoken);
} else {
console.log("Lay new access token bi loi " + response.error.message);
}
});
}
});
};
I try to search every where for this trouble 3 days without any clue. I there any one have experience? please help.
Many thanks
Doing this in a client is a bad idea because of the requirement to include the app secret in the actual client, which is very dangerous. It's best to call a endpoint on your server that handles this separately so that app secret stays in your controlled environment.
If in Advanced Settings of your FB App you have 'Remove offline_access permission' enabled, all your access tokens will be 60 days by default.
We ran into this same issue recently and this fixed the problem.
Hope this helps!
I found a simple solution to get extended access token using Jquery valide upto 2 months
Variables to pass to the URL:
var accessToken = 'CURRENT_ACCESS_TOKEN';
var appid = 'APPID';
var appsecret = 'APPSECRET';
Your URL should point to
var exchangeUrl = "https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&fb_exchange_token="+accessToken+"&client_id="+appid+"&client_secret="+appsecret;
Make an Ajax request as
$.ajax({
type: "GET",
url: exchangeUrl,
success: function(data)
{
extended = data.split('=');
extendedAT = extended['1'].replace('&expires','');
alert(extendedAT);
}
});