How to get an access token to read messages on Discord via API? - discord

I would like to use the Discord API to read messages from different servers (e.g., StableDiffusion).
I created a bot via the developer page: https://discord.com/developers/applications/ and I was able to make a basic REST call:
import requests
headers = {"Authorization": f"Bot {public_key}"}
url = 'https://discordapp.com/api/v9/users/#me'
response = requests.get(url, headers=headers)
response.raise_for_status()
response.json()
Unfortunately, I get 403 errors when trying to read messages from StableDiffusion:
import requests
headers = {"Authorization": f"Bot {public_key}"}
url = 'https://discord.com/api/v9/channels/1002292398703001601/messages?limit=50'
response = requests.get(url, headers=headers)
response.json()
{'message': 'Missing Access', 'code': 50001}
Where or how do I get the access token? Are there special permissions needed for the bot?
I selected the Administrator option under "General Permissions", which presumably enables everything.
My general account is already authorized to read messages from that Server; do those permissions transfer over to my bot?

Related

Can a POST request be redirected as another GET request

I am working on a react application, where there is a need to send the object parameters inside a body because of confidentiality. So I am making a POST request from the react app client-side to the backend server like this
axios
.post('htps://java.backend.xyz/path1', {
data: password,
})
.catch(function (error) {
handle(error);
});
After making this POST request there is a preflight request with "method = OPTIONS" and "URL= 'htps://java.backend.xyz/path1'"...to which java-backend-server responds with status_code=200.
After the above preflight request, java-backend-server addresses the POST request and instead of sending a response the java-backend-server respond with a GET request (i.e redirect) as for example:
https://express-app.xyz/path2?query_para1=abc&query_param2=123, requestMethod=GET
And in response to the above GET request, the express app responds with status_code=200
But immediately after this GET request, there is a preflight request with request Method=OPTIONS and having the same URL as above i.e
https://express-app.xyz/path2?query_para1=abc&query_param2=123, requestMethod=OPTIONS
and for this above OPTIONS request express server responds with a status_code=204 which means that the client doesn't need to navigate away from its current page...this is something prohibiting my app to make a final redirect i.e after the backend server responds with a GET request, my react app is not able to make a redirect even search engine does not update the redirect URL which is
https://express-app.xyz/path2?query_para1=abc&query_param2=123
So, here Is this even possible? I am assuming that the preflight request after the GET request prohibits the client side to be able to make a final redirect. Can someone please help me with this scenario
I am not sure if I understand your problem correctly but what you can do is send a post response which will which will indicate client to redirect to specific location.
This can be achieved by sending response with status code 302 and location in header (location:redirect_url)
For more info :- https://en.m.wikipedia.org/wiki/HTTP_302

Unable to set cookies in Chrome using Flask-JWT-Extended, React, and Axios

Background and Issues
I have a Flask back-end running in localhost:5000 and a React SPA running on localhost:3000.
I was able to make them talk but when trying to store the token generated from Flask into Browser's cookies 1) response headers does not contain any cookies when doing console.log(response) after a successful POST from axios and 2) the cookies are not being set. But when inspecting the network > Login.js header, I could actually see the Set-Cookie key exists as response's header. I've tried multiple solutions from Google and StackOverflow but no solution seems to work here and I really can't figure out what is going on as the request is being made successfully, and Chrome is allowing third party software to set the cookies. And even I can see the tokens from Network > Login.js header.
Steps
1) Users enters in their username and password and hit login.
2) Axios POST call is made to Flask's back-end.
3) Process the data and generates a couple of tokens and set them into cookies.
4) Browser's cookie are set with few tokens. <- this part is not working.
Code
Flask back-end token generation using flask-jwt-extended
# app_config related to flask-jwt-extended
CORS_HEADERS = "Content-Type"
JWT_TOKEN_LOCATION = ["cookies"]
JWT_COOKIE_SECURE = False
JWT_COOKIE_CSRF_PROTECT = True
# post method from flask-restful for LoginAPI class
def post(self):
email = request.json.get("email")
password = request.json.get("password")
# some processing here.....
payload = {
"email": email
}
access_token = create_access_token(identity=payload)
refresh_token = create_refresh_token(identity=payload)
response = jsonify({"status": True})
set_access_cookies(response, access_token)
set_refresh_cookies(response, refresh_token)
return response
CORS using flask-cors
# in below code, I had some issues with putting wildcard (*) into origin, so I've specified to the React SPA's host and port.
CORS(authentication_blueprint, resources={r"/authentication/*": {"origins": "http://localhost:3000"}},
supports_credentials=True)
React SPA - making a post call using axios
# also tried `axios.defaults.withCredentials = true;` but same result.
export const login = (email, password, cookies) => {
return dispatch => {
const authData = {
email: email,
password: password
};
let url = 'http://127.0.0.1:5000/authentication/login/';
axios.post(url, authData, {withCredentials: true)
.then(
response => {
console.log(response)
})
.catch(err => {
console.log(err)
});
dispatch(authSuccess(email, password));
}
};
Below image is the response from successful post call in axios.
I'm not sure whether it is normal but response's headers are not showing any of the cookies that I'm setting from the back-end.
And below image is from Network > header for login/
As shown, you can clearly see the token information with Set-Cookie key. I've also checked that they aren't secure.
And finally when I check my cookie tab from application > cookies, I do not see anything.
So the issues were coming from the localhost.
I have a Flask back-end running in localhost:5000 and a React SPA running on localhost:3000.
From above statement, to be very specific, I was running the back-end on localhost:5000 and running the React SPA on 127.0.0.1:3000.
Once I've changed the 127.0.0.1 to localhost, it worked like a charm.
And a side note, after playing around with CORS, I think it will be a lot easier to use Nginx and proxy_pass to pass the request coming from React SPA to back-end to avoid using CORS completely, because if one have to use the CORS in different environment such as test, staging and etcs, one would have to set up the CORS at the web server level e.g) Nginx anyway and it requires slightly different configuration that how I set up for local environment anyway.

React unable to send email with SendGrid

I am using react to send emails:
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(process.env.REACT_APP_SENDGRID);
const msg = {
to: 'test#example.com',
from: 'test#example.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>',
};
sgMail.send(msg);
But I got the following error:
Access to fetch at 'https://api.sendgrid.com/v3/mail/send'
from origin 'http://localhost:3000' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
The 'Access-Control-Allow-Origin' header has a value 'https://sendgrid.api-docs.io' that is not equal to the supplied origin.
Have the server send the header with a valid value, or, if an opaque response serves your needs,
set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
How do I fix it? Many thanks!
Sendgrid won't let you send an email directly using Javascript in the browser.
You will need to have a server set-up and use the server to send the email instead (using your favourite back-end framework/language, Node.js, php, Java, etc.).
The steps for sending a mail will be similar to this:
Write email details in the React application
Send a POST request to your server endpoint (for example, /sendemail) with the email data (recipient, title, content, etc.)
Receive Email data in the server and send it to Sendgrid api
Here is the official Sendgrid documentation regarding their CORS policy: https://sendgrid.com/docs/for-developers/sending-email/cors/

Redirect to login when API returns authentication failure

I have a setup with IdentityServer4 and an API that run together as the same project, and an MVC client. This works fine but at some point the client makes a call to the API and an authentication error (401) is returned because the access token has somehow become invalid. In this scenario, I want the client to invoke the login page on the server so the user can re-enter their credentials and then redirect back to the client.
string accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
using (HttpClient client = new HttpClient())
client.SetBearerToken(accessToken);
HttpResponseMessage response = await client.GetAsync("http://apiserver/method");
if (response.IsSuccessStatusCode) {
string content = await response.Content.ReadAsStringAsync();
forum = JsonConvert.DeserializeObject<Data>(content);
} else {
return Redirect(... url to server login with return URL here ...)
}
}
I'm not clear how to generate the url to the server with the right path and query to authenticate correctly and return back to the client. I've looked through the documentation and samples but none seem to address this scenario.
I'm not clear how to generate the url to the server with the right path and query to authenticate correctly and return back to the client. I've looked through the documentation and samples but none seem to address this scenario.
when you get unauthorized access status code 401 from the api, you have to first log the user out. By logging them out it will clear out the cookies and sign them out from the oidc as well. This will redirect the app to your login page as there will be no cookies to authenticate on the client.
await HttpContext.Authentication.SignOutAsync("Cookies");
await HttpContext.Authentication.SignOutAsync("oidc");
Another way is to check whether your access token has been expired beforehand i.e before making the api call. This will save you extra http call. But it depends on your application requirements.

OpenId Connect endpoint returns 'not found'

I am migrating OpenID 2.0 to OAuth 2.0 login (see https://developers.google.com/accounts/docs/OpenID?hl=ja). I want to map the new OpenID 2.0 identifiers to old/existing OpenID Connect identifiers, which I have in my DB.
I'm at the point of handling the OAuth response (redirect_uri), where I want to use the https://www.googleapis.com/oauth2/v3/token endpoint, to exchange the authorization code for an access token and an openid_id field, which I would use to select an existing user in my DB.
However, my call to https://www.googleapis.com/oauth2/v3/token returns 'not found'. Any clue why?
I'm using scribe 1.3.7, and this is my code:
OAuthService service = new ServiceBuilder().provider(Google2Api.class).apiKey(xxxxxxxx).apiSecret(yyyyyyyyyyyyyyy).callback(zzzzzzzzzzzzzzzzzzzz).scope("openid profile https://mail.google.com/ https://www.googleapis.com/auth/userinfo.email").build();
Token accessToken = service.getAccessToken(null, new Verifier(oauth_verifier);
OAuthRequest request = new OAuthRequest(Verb.GET, "https://www.googleapis.com/oauth2/v3/token");
request.addQuerystringParameter("format","json");
request.addQuerystringParameter(OAuthConstants.REALM, "http://*.unclestock.com");
service.signRequest(accessToken, request);
Response response = request.send();
// result -> not found
GET requests to https://www.googleapis.com/oauth2/v3/token return 'Not Found'. You need to use HTTP POST for the request.
Update line 3 of your code to the following, and try it again:
OAuthRequest request = new OAuthRequest(Verb.POST, "https://www.googleapis.com/oauth2/v3/token");
You can read more about exchanging the code for an access token and an ID Token in the official docs.

Resources