Laravel Passport authentication : how to use code and state? - oauth-2.0

I'm authenticating to Laravel (7.3) Passport with the following configuration:
nuxt.config.js
auth: {
redirect: {
login: '/login',
logout: '/login',
home: '/'
},
strategies: {
'laravel.passport': {
url: 'http://laravel.test',
client_id: '2',
client_secret: 'S0gpcgfIDgbvIHCL3jIhSICAiTsTUMOR0k5mdaCi',
redirect_uri: 'http://localhost:3000'
}
}
}
Authentication method in pages/login.vue:
async nuxtLaravelPassport() {
try {
const response = await this.$auth
.loginWith('laravel.passport')
.then(result => {
console.log(result)
})
} catch (err) {
console.log(err)
}
},
It brings me to the authentication page of Laravel, then I log in and I'm redirected to my Nuxt.js home page with a code and state as parameters.
What should I do with these code and state ? Get a token ? If yes, how ?

Related

SimpleGraphClient: Invalid token received

I started developing a new MS Teams Application and I am trying to authenticate a MS Teams user on my app's backend by following the source code of
https://github.com/OfficeDev/Microsoft-Teams-Samples/tree/main/samples/app-sso
But unfortunately when I am trying to create a SimpleGraphClient with the token acquired by this function
// Get Access Token
const getAccessToken = async(req) => {
return new Promise((resolve, reject) => {
const { tenantId, token } = reqData(req);
const scopes = ['User.Read']; //['User.Read', 'email', 'offline_access', 'openid', 'profile'];
const url = `https://login.microsoftonline.com/${ tenantId }/oauth2/v2.0/token`;
const params = {
client_id: process.env.MicrosoftAppId,
client_secret: process.env.MicrosoftAppPassword,
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: token,
requested_token_use: 'on_behalf_of',
scope: scopes.join(' ')
};
// eslint-disable-next-line no-undef
fetch(url, {
method: 'POST',
body: querystring.stringify(params),
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(result => {
if (result.status !== 200) {
result.json().then(json => {
// eslint-disable-next-line prefer-promise-reject-errors
reject({ error: json.error });
});
} else {
result.json().then(async json => {
resolve(json.access_token);
});
}
});
});
};
I am taking the exception :
throw new Error('SimpleGraphClient: Invalid token received.');
What am I doing wrong?

Rails API, devise user registration, CORs signup with Vue Js

I have a curious CORS error in a Rails API setup with post request from Vue signup,
Despite setting the values at localhost:8080 for the Vue app and localhost:3000 for the response, it still wont allow access.
Rails CORs settings are below.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'localhost:8080'
resource 'localhost:3000',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
The request method using Nuxt axios plugin is below'
// Check submit
signin () {
this.$plain.post( '/api/v1/sign_up/', { email: this.email, password: this.password, password_confirmation: this.password_confirmation} )
.then(response => this.signinSuccessful(response))
.catch(error => this.signinFail)
console.log({ email: this.email, password: this.password, password_confirmation: this.password_confirmation });
alert('Processing!');
},
And the axios plugin code itself is also below.
/* eslint-disable */
import axios from 'axios'
export default function ({ $axios, store }, inject) {
const API_URL = "http://localhost:3000"
const secured = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
"Content-Type": "application/json",
},
})
const plain = axios.create({
baseURL: API_URL,
withCredentials: true,
headers: {
"Content-Type": "application/json"
},
})
secured.interceptors.request.use((config) => {
const method = config.method.toUpperCase();
if (method !== "OPTIONS" && method !== "GET") {
config.headers = {
...config.headers,
"X-CSRF-TOKEN": localStorage.csrf,
};
}
return config;
});
secured.interceptors.request.use(null, (error) => {
if (error.response && error.response.config && error.response.status === 401) {
return plain
.post("/refresh", {}, { headers: { "X-CSRF-TOKEN": localStorage.csrf } })
.then((response) => {
localStorage.csrf = response.data.csrf;
localStorage.signedIn = true;
let retryConfig = error.response.config;
retryConfig.headers["X-CSRF"] = localStorage.csrf;
return plain.request(retryConfig);
})
.catch((error) => {
delete localStorage.csrf;
delete localStorage.signedIn;
location.replace("/");
return Promise.reject(error);
});
} else {
return Promise.reject(error);
}
})
inject('plain', plain)
inject('secured', secured)
}
It is getting rejected due to CORs policy for authenticated requests as in screenshot, and I tried changing "with-credentials" to false but got error bad request, any tips on this welcome?

Nuxt auth-next with keycloak CORS problem

Versions:
keycloak 12.0.2
nuxt: 2.14.6
nuxt/auth-next: 5.0.0-1622918202.e815752
Configs:
nuxt.config.js
auth: {
strategies: {
keycloak: {
scheme: '~/plugins/keycloak.js',
endpoints: {
authorization:'https://keycloak.bgzchina.com/auth/realms/bgzchina/protocol/openid-connect/auth',
token:'https://keycloak.bgzchina.com/auth/realms/bgzchina/protocol/openid-connect/token',
userInfo: "https://keycloak.bgzchina.com/auth/realms/bgzchina/protocol/openid-connect/token",
logout:'https://keycloak.bgzchina.com/auth/realms/bgzchina/protocol/openid-connect/logout',
},
responseType: 'id_token token',
clientId: 'centuari-portal-fe',
scope: ['openid'],
}
},
redirect: {
login: '/login',
logout: '/logout',
callback: '/callback',
home: '/',
}
},
router: {
middleware: ['auth']
},
due to a issue with current version nuxt/auth-next, I created a custom scheme by extending oauth2
/plugin/keycloak.js
import { Oauth2Scheme } from '~auth/runtime'
function encodeQuery(queryObject) {
return Object.entries(queryObject)
.filter(([_key, value]) => typeof value !== 'undefined')
.map(([key, value]) => encodeURIComponent(key) + (value != null ? '=' + encodeURIComponent(value) : ''))
.join('&')
}
export default class KeycloakScheme extends Oauth2Scheme {
logout() {
if (this.options.endpoints.logout) {
const opts = {
client_id: this.options.clientId,
post_logout_redirect_uri: this._logoutRedirectURI
}
const url = this.options.endpoints.logout + '?' + encodeQuery(opts)
window.location.replace(url)
}
return this.$auth.reset()
}
}
but when doing login, browser will block the token request due to CORS. keycloak server response for the preflight specify allowed method is POST, OPTIONS, but auth-next use GET to fetch token.
Is there any work around ?
You need to add/register the url into keycloak admin dashboard.
Go to keycloak admin dashboard
Menu Clients => select the client
On Settings tab, scroll down the page and find Web Origins. Add your frontend url (nuxt url) on it. Don't forget to add into Valid Redirect URIs too.

Nuxt.js exchanging authorization code for access token Oauth2

I'm trying to exchange the authorization code I got in the first step of the documentation for access token. Where I'm stuck is how to send a request for the token that contains the code I've just got with the first request.
This is my code:
auth: {
redirect: {
login: '/',
callback: '/auth'
},
strategies: {
wrike: {
scheme: 'oauth2',
endpoints: {
authorization: 'https://login.wrike.com/oauth2/authorize/v4',
token: 'https://login.wrike.com/oauth2/token',
logout: '/'
},
token: {
property: 'access_token',
type: 'Bearer',
maxAge: 1800
},
responseType: 'code',
grantType: 'authorization_code',
accessType: 'offline',
clientId: XXXX,
client_secret: YYYY
}
}
}
I can't figure it out how I should set up the redirect URI, in the client or in the server side? How should I do the second request? (This below)
POST https://login.wrike.com/oauth2/token
//Parameters:
client_id=<client_id>
client_secret=<client_secret>
grant_type=authorization_code
code=<authorization_code>
I think Edward is right. It doesn't seem to work. You can either do the custom schema which is what I am going to do, or you can do what I currently have which is something like this (of course ignore all the console.log and stuff like that):
const urlParams = new URLSearchParams(window.location.search)
const code = urlParams.get('code')
const state = urlParams.get('state')
console.log('state', state)
console.log('stateStorage', window.localStorage.getItem(state))
if ((code && state) && state === window.localStorage.getItem('state')) {
this.$axios.post('http://publisher-local.co.uk:8080/oauth/token', {
grant_type: 'authorization_code',
client_id: 5,
redirect_uri: 'http://localhost:3000/auth',
code_verifier: window.localStorage.getItem('verifier'),
code
}).then(response => {
this.$auth.setUserToken(response.data.access_token)
this.$auth.fetchUser()
})
}
So basically after you are redirected back to your client after logging in on the server page just look for the details in the URL and make the request yourself.

API authorization flow with Hapijs and oauth 2

We are using hapijs and oauth server for authentication. we need to implement role based authorization in hapijs. is below way is fine for hapijs.
Register authentication scheme
server.auth.scheme('custom', function (server, options) {
return {
authenticate: function (request, reply) {
// calling oauth flow for roles match
}
});
Register authentication strategy & adding auth,roles in server.route
server.auth.strategy('default', 'custom');
server.route({
method: 'GET',
path: API_Path,
config: {
roles: ['ADMIN', 'USER'],
auth : 'default'
},
handler: function (request, reply) {
return reply.act({
role: 'admin',
cmd: 'getInfo',
id: request.params.id
});
}
});
You should register a strategy and validate the credentials like this.
const validate = function (request, username, password, callback) {
const user = users[username];
if (!user) {
return callback(null, false);
}
Bcrypt.compare(password, user.password, (err, isValid) => {
callback(err, isValid, { id: user.id, name: user.name });
});
};
server.auth.strategy(strategy_name, scheme_name, { validateFunc: validate });
Your auth should have options like mode, scope, strategy etc
...
...
auth :{
mode:'required',
strategy:'strategy_name',
scope: ['ADMIN', 'USER']
},
...
...
You can use Bell

Resources