I'm building a GitHub Oauth app, and I'm trying to authenticate Octokit using an Oauth access_token that I'm getting when the user clicks sign in with Github.
The access_token I'm using has access to the repo scope, but when I try to authenticate Octokit with this token, I get: HttpError: A JSON web token could not be decoded
Here is my code:
let TOKEN = "<Token>"
const appOctokit = new Octokit({
auth: TOKEN
});
I've also tried authenticating like this:
const appOctokit = new Octokit({
authStrategy: createOAuthAppAuth,
auth: {
clientId: "<Client_ID>",
clientSecret: "<Client_Secret>",
},
});
but when I do that, and I try deleting an issue using octokit, I get an HttpError: Not Found error.
Related
I am trying Google Apps Script API. I receive this
Request is missing required authentication credential" error by trying service.scripts.run({ // params }).
Can somebody help me figure out, how to authenticate credentials?
I am using google.auth.OAuth2() for my authentication.
This is my code:
const service = google.script({ version: 'v1', auth });
await service.scripts.run({ scriptId, requestBody: { function: 'myFunction', devMode: true }});
service.scripts is already working fine with these methods:
await service.projects.create({ // params })
and
service.projects.updateContent({ // params })
Here are my scopes:
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/script.projects
https://www.googleapis.com/auth/script.scriptapp
I am expecting for the my Apps Script to run programmatically.
I have searched for an answer to this specifically but can't seem to find it. Apologies if it's a repeat.
I have the access token and the refresh token and want to send the emails using these tokens. The tokens are generated using the passport.js library and I am storing them in the DB along with other profile data. Like this
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_APP_CLIENT_ID,
clientSecret: process.env.GOOGLE_APP_CLIENT_SECRET,
callbackURL: process.env.GOOGLE_APP_CALLBACK_URL,
passReqToCallback: true
},(request:any,accessToken: string, refreshToken: string, profile: any, done: any)=>{
//save credentials in database
}));
Now using the access token and the refresh token I want to access the Gmail API. Contrary to the example (https://developers.google.com/gmail/api/quickstart/nodejs) provided by Google. In which they are providing the Oauth client created from executing Oauth2 flow.
What is needed is something like this
const gmail = google.gmail({version: 'v1', auth:{accessToken,refreshToken});
In summary: Pretty much what DalmTo said in his comment. You need to also add the client ID, secret and redirect URL.
Explanation: It may be a little hard to see but the sample that you provided does show how to authenticate with locally stored information. I'll try to simplify it.
The most relevant parts are under the authorize() function:
//first create a google.auth.OAuth2 object
//for this you still have to use your app's client_id, client_secret and redirect_uri
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
The sample app creates a token.json file that it uses to reauthenticate. It's just a simple object with the tokens (there are a couple additional fields which I removed since they are not relevant to this):
{
"access_token":"ya29...",
"refresh_token":"1//..."
}
Then the sample shows that you have to call setCredentials() on the oAuth2Client object using this token file that was created.
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
Then once you have set the credentials to the oAuth2Client object you can use it to authorize the API:
const gmail = google.gmail({version: 'v1', oAuth2Client});
The sample works with a locally stored file, but since you store the tokens in your database in your case it might look more like this:
//get the tokens from somewhere in your database
const tokens = {
"access_token" : ACCESS_TOKEN,
"refresh_token" : REFRESH_TOKEN
}
const oAuth2Client = new google.auth.OAuth2(
process.env.GOOGLE_APP_CLIENT_ID,
process.env.GOOGLE_APP_CLIENT_SECRET,
process.env.GOOGLE_APP_CALLBACK_URL
);
oAuth2Client.setCredentials(tokens);
const gmail = google.gmail({version: 'v1', oAuth2Client});
You'll probably also need to handle reauthorization in case that the refresh token has expired or the user has revoked access but I hope this gives you a general idea.
More info: Google API's Node.js Client
I am using msal for getting tokens as per below:
const msal = require('#azure/msal-node');
const msalConfig = {
auth: {
clientId: config.MS_CLIENT_ID,
authority: config.AAD_ENDPOINT + 'consumers', //config.TENANT_ID,
clientSecret: config.MS_CLIENT_SECRET,
}
};
const cca = new msal.ConfidentialClientApplication(msalConfig);
const authCodeUrlParameters = {
scopes: ["Mail.ReadWrite"],
redirectUri: config.MS_REDIRECT_URI,
};
// get url to sign user in and consent to scopes needed for application
cca.getAuthCodeUrl(authCodeUrlParameters);
let tokenReq = {
code: ctx.params.Token,
scopes: ["Mail.ReadWrite"],
redirectUri: config.MS_REDIRECT_URI
}
const tokenRes = await cca.acquireTokenByCode(tokenReq);
I am not getting refresh token from acquireTokenByCode method
First to implement refresh token, you need the scope offline_access incorporated in your flow.
That said, Msal-Node des not expose the refresh token. It will use the refresh token internally to renew the access token. Check this thread for more details. You use acquireTokenSilent when you need an access token as Msal will take care of managing the refresh token.
Using the Twitter API, I'm trying to post a tweet on behalf of a Twitter user.
I'm using node and the passport-twitter and twit modules.
Some resources:
I followed this video tutorial NodeJS and ExpressJS: Using Twitter
authentication via Passport.
Sourcecode for the tutorial
here.
Passport-twitter documentation
twit documentation
I successfully authenticated with passport-twitter following the tutorial above.
I also successfully posted using twit on my twitter developer account.
However, I'm having trouble combining these two things; trying to post to twitter on behalf of another user. For that, I need to get the user's access token and access token secret. Then, I need to make a post request to the Twitter API with that information.
I'm not sure where to put the post request in the passport-twitter code. I tried putting it in the second route which is the URL to which Twitter redirects the user after they have signed in.
app.get('/twitter/login', passport.authenticate('twitter'))
app.get('/twitter/return', passport.authenticate('twitter', {
failureRedirect: '/'
}), function(req, res) {
//Post using twit
//grab access token and access token secret from the request query
const access_token = req.query.oauth_token;
const access_token_secret = req.query.oauth_verifier;
//set the configurations with the access token and access token secret that we just got
const config = {
consumer_key: <consumer key here>,
consumer_secret: <consumer secret here>,
access_token,
access_token_secret,
timeout_ms: 60*1000,
strictSSL: true
}
//pass in the configurations
var T = new Twit(config);
//post
T.post('statuses/update', { status: 'hello world!' }, function(err, data, response) {
if (err)console.log("oops, didn't tweet: ", err.message);
})
res.redirect('/');
})
But I got an error: Invalid or expired token.
I expected it to work because the authentication worked.
This is my first time using OAuth so perhaps I misunderstand how this all works.
Where am I supposed to put the post request?
UPDATE:
I tried posting to my dev account, using my dev account's access token and secret. It worked. Which lead me to believe there is something wrong with the access token and secret for the user.
I think I know partially what’s going.
I assumed that the property oauth_verifier found in the request query object was the access token secret.
const access_token_secret = req.query.oauth_verifier;
But now I don’t think oauth_verifier is the same as the access token secret. oauth_verifier has less characters than my dev account’s access token secret. So it seems that the datatypes are different.
But now I’m trying to figure out where the access token secret is? There are only two properties in the request query object (req.query);
oauth_token
oauth_verifier
Where’s the access token secret for the user?
I solved my issue. It was in the documentation for passport-twitter all along. Man, I spent days on this issue.
The strategy also requires a verify callback, which receives the access token and corresponding secret as arguments, as well as profile which contains the authenticated user's Twitter profile.
-from passport-twitter readMe
In the example in the docs, you can see token and tokenSecret in the params.
passport.use(new TwitterStrategy({
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
callbackURL: "http://127.0.0.1:3000/auth/twitter/callback"
},
function(token, tokenSecret, profile, cb) {
User.findOrCreate({ twitterId: profile.id }, function (err, user) {
return cb(err, user);
});
}
));
I read this and saw this before. But assumed this was the the consumer key and consumer secret. I didn't realize it was what I was looking for: the access token and access secret.
So your post to twit would go something like this:
passport.use(new Strategy({
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
callbackURL: 'http://localhost:3000/twitter/return'
}, function(token, tokenSecret, profile, callback) {
const configs = createConfigs(token, tokenSecret);
// Post to twitter
var Twit = require('twit')
var T = new Twit({
consumer_key: '...', //get this from developer.twitter.com where your app info is
consumer_secret: '...', //get this from developer.twitter.com where your app info is
access_token: token,
access_token_secret: tokenSecret,
timeout_ms: 60*1000, // optional HTTP request timeout to apply to all requests.
strictSSL: true, // optional - requires SSL certificates to be valid.
})
//
// tweet 'hello world!'
//
T.post('statuses/update', { status: 'hello world!' }, function(err,
data, response) {
console.log(data)
})
return callback(null, profile);
}));
On my front end, I'm using vue.js (not that that matters) and with the Google OAuth flow, I get back an id_token from:
let googleAuthIdToken = await this.auth2.currentUser
.get()
.getAuthResponse().id_token;
I want to then pass that token to my node.js server (Express / Passport) to verify that the user is allowed to login.
I want to use passport and send back a JWT to the front end in my response.
Can someone please guide me as to how to accomplish this?
It is easier to make use of a node module called googleapis, After installation, import the module.
import { google } from 'googleapis';
Then you need to create an OAuthClient by specifying the CLIENT_ID, CLIENT_SECRET, REDIRECT_URL.
const oauth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLIENT_SECRET,
REDIRECT_URL,
);
Then you can get the token from google by using the oauth2Client.
const {tokens} = await oauth2Client.getToken(code);
oauth2Client.setCredentials(tokens);
Inorder to obtain the neccessary user information to store in your own database, You need to call this method.
const plus = google.plus({ version: 'v1', oauth2Client });
const me = await plus.people.get({ userId: 'me' });
me will contain the user information that you are looking for, once you obtain the user information you can then store it using passport js.