How to get user information after login in laravel fortify - laravel-fortify

I am using laravel fortify in my single page vue application. When i send XHR request to sitePath + '/login' i get {two_factor: false} in response and user is logged in. How can i add user information so i can save the data in local storage.
let response = await this.$root.requestPost(data, url);
async requestPost(data, requestUrl) {
const response = await axios.post(requestUrl, {
// ...data
}).catch(error => {
//
});
return response;
},

Sorry for late answer.
But today I have solved same problem.
In FortifyServiceProvider's register() method, you need implement own LoginResponse:
$this->app->instance(LoginResponse::class, new class implements LoginResponse {
public function toResponse($request)
{
/**
* #var User $user
*/
$user = $request->user();
return $request->wantsJson()
? response()->json(['two_factor' => false, 'email' => $user->email ])
: redirect()->intended(Fortify::redirects('login'));
}
});
Documentation - https://laravel.com/docs/8.x/fortify#customizing-authentication-redirects

Related

How can I access the logged in user name on Netlify?

I'm having trouble understanding how handle functions on Netlify. In particular, I want to access the user's id when they login.
I have enabled identity on my netlify site and I can login and log out.
<button data-netlify-identity-button id="login"></button>
I have created a function identity-login that I think should handle the user's details, but I cannot see how to utilise it on the web-page
// functions/identity-login.js
exports.handler = async function (event, context) {
const { identity, user } = context.clientContext;
console.log(identity, user)
return {
statusCode: 200,
body: 'hello'
}
};
The function endpoint is
https://silly-parrot.netlify.app/.netlify/functions/identity-login
I have this in the script on my page, but I don't know how to call it or if it's correct
async function apiCall() {
const url = `/.netlify/functions/identity-login`;
try {
const response = await fetch(url);
const data = await response;
console.log(data)
return data;
} catch (err) {
console.log(err);
}
}
What should I do?
I now realise that I was taking the wrong approach. It is not necessary to use the Netlify identity-login event. The netlifyIdentity object provides the necessary functionality for identifying when the user logs in or logs out and to discover whether or not the user is logged in when the page loads (init). The user identity is contained in the user.token.access_token
The following code is within my main js script (you will of course need to access the netlifyIdentity object)
<script type="text/javascript" src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
And then setup async functions to handle the authorisation events
<script>
var token = '';
var logged_in = false;
async function started() {
logged_in = false;
netlifyIdentity.on('init', async user => {
if(user) {
token = user.token.access_token;
logged_in = true;
}
console.log('init', logged_in, token);
})
netlifyIdentity.on('login', user => {
if(user) {
logged_in = true;
token = user.token.access_token;
}
console.log('log in', logged_in, token);
})
netlifyIdentity.on('logout', () => {
token = '';
logged_in = false;
console.log('log out', logged_in, token);
})
}
started()
</script>

razor pages with firebase auth - where to put this token ? :)

i am working on web site with razor pages. part of the site should be accessed only by registred users. decided to go with firebase authentification (now with login and password ).
created everything necessary in firebase.
created backend code for user registration - works well.
created area which requires authorisation
services.AddRazorPages(options =>
{
options.Conventions.AuthorizeAreaFolder("User", "/");
})
added jwt middleware
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
added code to login page to call firebase to get token
function login()
{
firebase.auth().signInWithEmailAndPassword(email, password)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
// ...
alert("signed");
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
alert(errorMessage);
});
}
got token from firebase.
if i'd call service next, i'd simply put token in "bearer" header.
tried to find how to add header to current browser for future requests and failed.
as i understand, i need this token to be added to auth header ? how ? :)
feeling dumb ;( tried to google, but most samples are for using this token later with api calls.
or i am going in the wrong direction?
tia
ish
well. it seems that it is not possible to add bearer from js, so i switched to cookies
in startup.cs use cookies
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = context.Request.Cookies["bearer"];
return Task.CompletedTask;
}
};
code to login with firebase, put token into the cookie and redirect
function login() {
firebase.auth().signInWithEmailAndPassword(email, password)
.then((userCredential) => {
// Signed in
var user = userCredential.user;
firebase.auth().currentUser.getIdToken(true).then(function (idToken)
{
document.cookie = "bearer" + "=" + idToken;
window.location.href = "/user/index";
}).catch(function (error) {
// Handle error
});
alert("signed");
})
.catch((error) => {
var errorCode = error.code;
var errorMessage = error.message;
alert(errorMessage);
});
}
or the same with firebaseUI
function login1()
{
ui.start('#firebaseui-auth-container', {
signInSuccessUrl: '/User/index',
signInOptions: [
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
requireDisplayName: false
}
],
callbacks:
{
signInSuccessWithAuthResult: function (authResult, redirectUrl)
{
var user = authResult.user;
firebase.auth().currentUser.getIdToken(true).then(function (idToken) {
document.cookie = "bearer" + "=" + idToken;
}).catch(function (error) {
// Handle error
});
return true;
}
}
});
}

Sequelize model property undefined Express.js controller after auth with passport-jwt

I am using passport-jwt to verify access to a given route in express.js, and then return a Sequelize model to the final controller. The code looks like:
The auth strategy:
const passportStrategy = passport => {
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: config.auth.ACCESS_TOKEN_SECRET
};
passport.use(
new Strategy(options, async (payload, done) => {
try {
const user = await User.findOne({ where: { email: payload.email }});
if (user) {
return done(null, {
user
});
}
return done(null, false);
}
catch (error) {
return done(error, false)
}
})
);
};
The route with the auth middleware
router.get('/:user_id/psy', passport.authenticate('jwt', { session: false }), patientsController.getPatientPsy);
The controller function
const getPatientPsy = async (req, res) => {
const authenticatedUser = req.user;
if (authenticatedUser.userType !== "patient") {
res.status(500).send("Big time error");
}
}
If I console.log(authenticatedUser) in the getPatientPsy() controller it successfully prints the Sequelize model with it's dataValues and so on, but when I try to access any property, be it userType or any other it consistently returns undefined.
In the passport-jwt authentication once a User has been found that matches the extracted JWT token, afaik it is returned synchronously and made it available in the req.user object, and I can print it with console.log, but why can't I access the model's properties?
I've tried to make the getPatientPsy() controller a sync function but it doesn't work either.
Thank you.
All right this is embarrassing, by default Passport.js returns the done(null, user) in the req.user property, and since I am returning { user }, I had to access through req.user.user.

Problem with interpreting route resource type for the RelatedPeople model

Hypothesis: I think it is the pluralization of resource or model, I am not sure.
My code:
Route web:
Route::group(['middleware'=> 'auth'], function() {
Route::resource('relatedPersons', 'RelatedPeople\RelatedPeopleController')
->only(['store','update','destroy'])
->middleware('can:relatedPeoples');
});
Note: the model is relatedPeople, but for testing purposes in the definition of the route leave it like this relatedPersons.
RelatedPeople(Model):
<?php
namespace App;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
class RelatedPeople extends Model
{
protected $fillable = [
'name',
'phone',
'email',
'detail',
'case_report_id'
];
public function getCreatedAtAttribute($value)
{
return Carbon::parse($value)->format('Y-m-d H:m');
}
public function getDetailAttribute($value)
{
return $value ?? "Sin detalle.";
}
}
RelatedPeopleController:
<?php
namespace App\Http\Controllers\RelatedPeople;
use App\Http\Controllers\Controller;
use App\RelatedPeople;
use Illuminate\Http\Request;
class RelatedPeopleController extends Controller
{
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$rules = [
'email'=> "required|unique:related_people"
];
$this->validate($request, $rules);
$relatedPeople = RelatedPeople::create($request->all());
return response()->json($relatedPeople, 200);
}
}
Frontend vuejs with axios:
onSubmit() {
let formData = new FormData(this.$refs.create)
formData.append('case_report_id', this.case_id)
axios.post('relatedPersons', formData).then( (response) => {
if ( response.status == 200 ) {
this.$emit('addRelatedPerson', response.data)
this.$toasterE.success("Related people create", { mark:1 })
this.$nextTick(() => {
this.$refs.form.reset()
this.form = form()
});
}
}).catch( (err) => {
this.exception(err)
})
}
The above code every time I run it goes into the catch and returns this error:
{"error": "The POST method is not supported for this route. Supported methods: GET, HEAD, PUT, PATCH, DELETE.", "code": 405}
Tests I've already done:
change resource name
In the model add table name protected $ table = "related_people"
Define a get (index) method to the controller to know that at least the request reaches the controller and only the GET method works, the rest do not work.
I will keep looking for a solution, thank you in advance.
Well after almost exploding my head I found that it was a mistake that the solution is in my face, not in my turquoise eyes but in front of my face.
The solution is:
Frontend vuejs with axios( before ):
onSubmit() {
let formData = new FormData(this.$refs.create)
formData.append('case_report_id', this.case_id)
axios.post('relatedPersons', formData).then( (response) => {
if ( response.status == 200 ) {
this.$emit('addRelatedPerson', response.data)
this.$toasterE.success("Related people create", { mark:1 })
this.$nextTick(() => {
this.$refs.form.reset()
this.form = form()
});
}
}).catch( (err) => {
this.exception(err)
})
}
Frontend vuejs with axios( solved ):
onSubmit() {
let formData = new FormData(this.$refs.create)
formData.append('case_report_id', this.case_id)
axios.post('/relatedPersons', formData).then( (response) => {
if ( response.status == 200 ) {
this.$emit('addRelatedPerson', response.data)
this.$toasterE.success("Related people create", { mark:1 })
this.$nextTick(() => {
this.$refs.form.reset()
this.form = form()
});
}
}).catch( (err) => {
this.exception(err)
})
}
If you haven't seen it yet, it's the route definition '/relatedPersons'
axios.post('/relatedPersons', formData).then( (response) => {
Now because of this problem, suppose I access the path axios.post('relatedPeoples', data) and the url of the application is test.dev/cases/1, the result of the request would be test.dev/cases/relatedPeoples and here the problem.
laravel tells me if the route exists but that method is not supported.
I hope my mistake helps many.

Migrate ADAL.js to MSAL.js

I have a SPA which uses the solution provided here to authenticate with Azure AD and everything works as expected. Now I want to migrate this to use MSAL.js.
I use below for login:
import * as MSAL from 'msal'
...
const config = {
auth: {
tenantId: '<mytenant>.com',
clientId: '<myclientid>',
redirectUri: <redirecturi>,
},
cache: {
cacheLocation: 'localStorage',
}
};
const tokenRequest = {
scopes: ["User.Read"]
};
export default {
userAgentApplication: null,
/**
* #return {Promise}
*/
initialize() {
let redirectUri = config.auth.redirectUri;
// create UserAgentApplication instance
this.userAgentApplication = new MSAL.UserAgentApplication(
config.auth.clientId,
'',
() => {
// callback for login redirect
},
{
redirectUri
}
);
// return promise
return new Promise((resolve, reject) => {
if (this.userAgentApplication.isCallback(window.location.hash) || window.self !== window.top) {
// redirect to the location specified in the url params.
}
else {
// try pull the user out of local storage
let user = this.userAgentApplication.getUser();
if (user) {
resolve();
}
else {
// no user at all - go sign in.
this.signIn();
}
}
});
},
signIn() {
this.userAgentApplication.loginRedirect(tokenRequest.scopes);
},
And then I use below to get the token:
getCachedToken() {
var token = this.userAgentApplication.acquireTokenSilent(tokenRequest.scopes);
return token;
}
isAuthenticated() {
// getCachedToken will only return a valid, non-expired token.
var user = this.userAgentApplication.getUser();
if (user) {
// get token
this.getCachedToken()
.then(token => {
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
// get current user email
axios
.get('<azureapi-endpoint>' + '/GetCurrentUserEmail')
.then(response => { })
.catch(err => { })
.finally(() => {
});
})
.catch(err => { })
.finally(() => { });
return true;
}
else {
return false;
}
},
}
but after login I get below error:
Access to XMLHttpRequest at 'https://login.windows.net/common/oauth2/authorize?response_type=code+id_token&redirect_uri=<encoded-stuff>' (redirected from '<my-azure-api-endpoint>') from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Also the token that I get seems to be invalid as I get 401 errors trying to call api using the token. Upon checking the token against https://jwt.io/ I get an invalid signature.
I really appreciate anyone's input as I've already spent good few days and haven't got anywhere yet.
I'm not sure if this is your issue. however, for msal.js, in the config, there is no tenantId parameter, it's supposed to be authority. Here is a sample for graph api using msal.js
https://github.com/Azure-Samples/active-directory-javascript-graphapi-v2
specifically: the config is here: https://github.com/Azure-Samples/active-directory-javascript-graphapi-v2/blob/quickstart/JavaScriptSPA/authConfig.js
as per here, https://learn.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications it is supposed to be hitting login.microsoftonline.com not login.windows.net