How i can get Token from headers? - flutter

I did authorization via http. post, send a JSON Body with username and password, in the response I get a Header, the Header has a token, it is stored in 'set_cookie: Authorization=token', how do I get it and write it to the storage?

You can get the cookie from the response of login request using the following code
HttpClient _httpClient = new HttpClient();
HttpClientRequest request = await _httpClient.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
HttpClientResponse response = await request.close();
print(response.cookies); // this is a List<Cookie>, you can iterate and find the required cookie
Now you can store the cookie using shared_preference plugin, and use it in your all the future requests.
HttpClient client = new HttpClient();
HttpClientRequest clientRequest =
await client.getUrl(Uri.parse("http: //www.example.com/"));
clientRequest.cookies.add(Cookie("sessionid", "asdasdasqqwd"));
You can also explore dio library and use AuthInterceptor to add the token for all the requests for you.

Related

Flutter post request headers do not appear on Google Cloud Function

I am doing a post request in flutter to a google cloud function:
final uri = Uri.parse(
'https://example.cloudfunctions.net/send_to_queue');
final bearer = 'Bearer ${await user.getIdToken()}';
final response = await http.post(uri, body: json.encode(data),
headers: {HttpHeaders.authorizationHeader: bearer, 'Content-Type': 'application/json'});
In the Google Cloud I print(request.headers) I see a bunch of headers but no Authorization or Content-Type headers.
What should I do?
P.S. Same issue in here Flutter calling firebase cloud function admin.auth.updateUser but I don't want to use a callable function
The browser was sending an OPTIONS request (preflight) before the POST.
I needed to change the Google Cloud Function to handle this:
def main(request):
# Set CORS headers for the preflight request
if request.method == 'OPTIONS':
# Allows GET requests from any origin with the Content-Type
# header and caches preflight response for an 3600s
headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '3600'
}
return ('', 204, headers)
# Get token from request
token = request.headers.get('Authorization').split('Bearer ')[1]
etc..

Dio dart/Flutter get and set cookie

I would like to do a set cookies, do a get request and after get the cookies.
In python it will be this:
> import requests cookies = {'status': 'working','color':'blue'}
> response = session.get('https://google.com/', cookies=cookies)
> print(session.cookies.get_dict())
Do you know how to flutter it? I tried something like this but it doesn't seem to have a cookie in the response and the cookie doesn't seem to be sent
Map<String, String> headers = {
"status":"working",
"color":"blue"
};
final BaseOptions dioBaseOptions = BaseOptions(
baseUrl: 'https://google.com',
headers: {
'Cookie': headers,
},
);
dio = Dio(dioBaseOptions);
var cookieJar=CookieJar();
dio.interceptors.add(CookieManager(cookieJar));
var response = await dio.get('https://google.com/');
Cookie is set by a server in a response header and a browser sends it back in a request header.
After receiving an HTTP request, a server can send one or more Set-Cookie headers with the response. The browser usually stores the cookie and sends it with requests made to the same server inside a Cookie HTTP header.
See Using HTTP cookies for details.
CookieManager does this for dio and Flutter.
To access Cookies in a dio response
final cookies = response.headers['set-cookie']

Autorization using bearer token failing

Friends
I am accessing an API using bearer token authorization and getting HTTP status 401.
The problematic code is Dart code (in a Flutter app). I have Swift code that accesses the same API so I can check the headers I am passing.
The Dart code:
var client = http.Client();
var url = Uri.https(<site>, <path>);
Map<String, String> body = {
<Hash entries to define request>
};
var headers = <String, String>{
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
"Accept" : "application/json, text/javascript, */*; q=0.01",
"Authorization" : "Bearer <Hex token>",
};
var response = await client.post(url, headers: headers, body: body);
http is from: import 'package:http/http.dart' as http;
The hex token is taken from a successful login. It is the same as I see after a successful login with the Swift app.
The "Accept" and "Content-Type" are also the same as the Swift app.
In result the statusCode is 401 and reasonPhrase is "Unauthorized"
The Swift app is working perfectly
This was not the problem I thought.
The Authorization header is ignored by the server and it does some cookie magic to authorise.
In Swift the cookies were set without my intervention. So I never understood that the Bearer.... authorization was ignored.

Works via Postman but not in Flutter: API call with GCS pre-signed URL

I'm trying to upload a video file to GCS using a pre-signed url. I've managed to create the url via Google but now I am facing a problem using it.
Upload works in Postman, got response 200.
postman body, postman params
Code copied from Postman results in 403 Forbidden (SignatureDoesNotMatch):
Future<http.StreamedResponse> uploadVideo(
{required String uploadURL, required String filePath}) async {
var headers = {'Content-Type': 'application/octet-stream'};
var request = http.MultipartRequest('PUT', Uri.parse(uploadURL));
request.files.add(await http.MultipartFile.fromPath('file', filePath));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
} else {
print(response.reasonPhrase);
}
return response;
}
This is the error I am getting from Google:
<?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your Google secret key and signing method.</Message><StringToSign>GOOG4-RSA-SHA256
20210803T082850Z
20210803/auto/storage/goog4_request
6d513846a3db49f949b0d2eea8f04b90f918b3b94588c3ed55ed3620b7d7e1f6</StringToSign><CanonicalRequest>PUT
/phonedo-interviews/app-test/007/2.mp4
X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Credential=interviews%40interviews-317011.iam.gserviceaccount.com%2F20210803%2Fauto%2Fstorage%2Fgoog4_request&X-Goog-Date=20210803T082850Z&X-Goog-Expires=900&X-Goog-SignedHeaders=content-type%3Bhost
content-type:multipart/form-data; boundary=dart-http-boundary-6w1yq6BQN3EkGBrhHZnwidOXZsBecsgSwTT3nBjB9vQCToHt0cg
host:storage.googleapis.com
content-type;host
UNSIGNED-PAYLOAD</CanonicalRequest></Error>
Note: I needed Content-Type to be application/octet-stream so I disabled that header in Postman's automatic headers and added Content-Type manually. When I didn't do that I also got 403.
The solution was to send the file in binary.
Here is the working code:
Future<http.Response> uploadVideo(
{required String uploadURL, required String filePath}) async {
var response = await http.put(
Uri.parse(uploadURL),
headers: {'content-type': 'application/octet-stream'},
body: File(filePath).readAsBytesSync(),
);
In your Postman headers, a Token is given to GCS (first line). Given that you need authorization, Postman probably has this Token saved somewhere application-wise.
In this flutter code, the headers you're giving do not include an Auth token and therefore you're receiving a 403 error.

Get user profile from TFS REST API using credentials with RestSharp

var client = new RestClient("https://app.vssps.visualstudio.com/_apis/profile/profiles/me?api-version=1.0");
var request = new RestRequest(Method.GET);
var authenHeader = new AuthenticationHeaderValue("Bearer",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", username, password))));
request.AddHeader("Authorization", authenHeader.ToString());
request.AddHeader("Accept", "application/json");
IRestResponse response = client.Execute(request);
Response :
StatusCode: NonAuthoritativeInformation,
Content-Type: text/html;
.
.
Or this request can use only personal access token to get it?
You must use OAuth with the profiles API, it doesn't support basic auth.