How can I use Laravel's Passport package to authenticate a different password column.
If i want to authenticate from a different 'username' column, it can be done with the following code:
public function findForPassport($username) {
return $this->where('id', $username)->first();
}
It will take Id, as the column. What if I want to use a different 'password' column. A column in the table with a different name such as 'uid_token'.
Adding this validateForPassportPasswordGrant method to User model did the job for me ("PasswMd" - custom column name):
public function validateForPassportPasswordGrant($password)
{
return Hash::check($password, $this->PasswMd);
}
There's a method the Passport/Bridge asks for called validateForPassportPasswordGrant($password) that you can override in your user model, if you don't override this it will look for a password column in your user table. I'm not entirely sure why they haven't configured it to use Authenticatable method getAuthPassword...
While the above solutions are great but there is another way to achieve it and it worked for me in Laravel 8.
For future readers I provide the code down here, they need to add to their models and return the custom password column like so.
public function getAuthPassword()
{
return $this->PasswMd;
}
Related
I'm working in VisualStudio on a Xamarin project.
I have a ParseObject subclass. It has a field "SentBy" that links to a ParseUser. It's constructed like this:
[ParseClassName("Beacon")]
public class Stuff_ParseBeacon : ParseObject
{
public Stuff_ParseBeacon() { }
[ParseFieldName("sentBy")]
public ParseUser SentBy
{
get { return GetProperty<ParseUser>(); }
set { SetProperty(value);}
}
}
I'm trying to include a parameter that doesn't need to be in the ParseClass on the server, which gets the data stored under "phoneNumber" from the linked user. So, like this:
public string SentByPhoneNumber
{
get
{
return SentBy.Get<string>("phoneNumber");
}
}
But I keep getting the error that there's no such key in that ParseUser--which is false, because all my ParseUsers store a phone number.
What am I doing wrong?
(BTW, in case it matters: I'm trying to use SentByPhoneNumber as a bindable property)
I don't think this is the best way to do it, but this is what I ended up doing.
I just added a phoneNumber field to the Beacon class, and it gets directly filled by the user who creates the Beacon--the user who gets stored in the SentBy field.
The problem with this is that the won't automatically update if I change the phoneNumber on the SentBy user.
This is pretty much exactly what I didn't want to do in my question.
So I'm sure there's a better way to refer to a field on a stored user than manually putting that data in the referring class at the time of creation, but it's what I've had to do to move on.
I have below code implemented Web API (.net Framework 4.5.2). When I make a call "http://localhost:3000/123" - It fetches user details whose id is 123.
If I make "http://localhost:3000/Class1/?status=Active" - It fetches user details who belong to Class 1 and status as active. Same I converted to .net core and eventhough I mentioned FromQuery, call always goes to ":http://localhost:3000/123"
public class UserController : Controller
{
private Repository repository;
[HttpGet("{id}")]
public object Get(string id)
{
return repository.GetUser(id) ?? NotFound();
}
[HttpGet("{group}")]
public object Get(string group, Status status)
{
// Get the User list from the group and whose status is active
}
}
Please let me know how to resolve this without changing Route Parameter.
Simply, you have two conflicting routes here. There's no way for the framework to know which to route to, so it's just going to take the first one. As #Nkosi indicated, if there's some kind of constraint you can put on the param, that will help. You may not be able to restrict to just ints, but perhaps there's a particular regex, for example, that would only match one or the other. You can see your options for constraining route params in the relevant docs.
If there's no clear constraint you can apply that will not also match the other, then you're mostly out of luck here. You can simply change one of the routes to be more explicit, e.g. [HttpGet("group/{group}")]. If the route absolutely must be the same, your only other option is to have one action handle both cases, branching your code depending on some factor.
[HttpGet("{id}")]
public object Get(string id, Status? status = null)
{
if (status.HasValue)
{
// Note: treat `id` as `group` here.
// Get the User list from the group and whose status is active
}
else
{
return repository.GetUser(id) ?? NotFound();
}
}
That may not be the best approach (branching on presence of status), but it's just an example. You'd need to decide what would work best here.
I'm trying to figure out whats the best way to have multiple Get actions in a REST controller.
I would like to do something like this:
Get By Id:
public ResponseType Get(Guid id)
{
// implementation
}
Get By Enum Type:
public ResponseType Get(EnumType type)
{
// implementation
}
Get By Other Enum Type:
public ResponseType Get(OtherEnumType otherType)
{
// implementation
}
etc..
Now when I do something like that, I get the next error message:
Multiple actions were found that match the request
I understand why I get the message and I was thinking how is the best way to do something like that (I want to stick with REST).
I know I can add a route like this:
routeTemplate: "api/{controller}/{action}/{id}"
But then I would need to change the action names and the urls - And this seems like a workaround when we are talking about rest.
Another thing I thought was to create multiple controllers with one Get - But that seems even wronger.
The third workaround was to handle one Get action with an input param that will have the state:
public ResponseType Get(ReqeustObj obj)
{
switch(obj.RequestType)
{
case RequestType.GetById:
// etc...
}
}
Anyway, I would like to know whats the best way to do something like that in REST (WebApi).
As you now, when Web API needs to choose an action, if you don't specify the action name in the route, it looks for actions whose name starts with the method name, GET in this case. So in your case, it will find multiple methods.
But it also try to match the parameters. So, if you include the parameters as part of the url (route parameters) or the query string, the action selector will be able to choose one of the available methods.
If you don't specify a parameter or specify the id in the url (or even in the query string) it should invoke the first overload. If you add the parameter name of the second action in the query string like this: ?type=VALUE it should choose the corresponding overload, and so on.
The question is that the parameter names must be different, or it will not be able to choose one or the other among all the overloads.
For example, if you use the urls in the comments in your browser, you'll see how the right method is chosen:
public class TestController : ApiController
{
// GET api/Test
public string Get()
{
return "without params";
}
// GET api/Test/5
public string Get(int id)
{
return "id";
}
// GET api/Test?key=5
public string Get(string key)
{
return "Key";
}
// GET api/Test?id2=5
public string Get2(int id2)
{
return "id2";
}
}
NOTE: you can also use route constraints to invoke differet methods without using query string parameters, but defining different route parameter names with different constraints. For example you could add a constraint for id accepting only numbers "\d+" and then a second route which accepts "key" for all other cases. In this way you can avoid using the query string
Using FluentMigrator, the default creation of a Column using .AsString() results in an nvarchar(255). Is there a simple way (before I modify the FluentMigrator code) to create a column of type nvarchar(MAX)?
You could create an extension method to wrap .AsString(Int32.MaxValue) within .AsMaxString()
e.g.
internal static class MigratorExtensions
{
public static ICreateTableColumnOptionOrWithColumnSyntax AsMaxString(this ICreateTableColumnAsTypeSyntax createTableColumnAsTypeSyntax)
{
return createTableColumnAsTypeSyntax.AsString(int.MaxValue);
}
}
OK, I found it. Basically, use .AsString(Int32.MaxValue). Pity there's not a .AsMaxString() method, but I guess it's easy enough to put in...
You can use AsCustom("nvarchar(max)") and pack it to extension
If you often create columns/tables with the same settings or groups of columns, you should be creating extension methods for your migrations!
For example, nearly every one of my tables has CreatedAt and UpdatedAt DateTime columns, so I whipped up a little extension method so I can say:
Create.Table("Foos").
WithColumn("a").
WithTimestamps();
I think I created the Extension method properly ... I know it works, but FluentMigrator has a LOT of interfaces ... here it is:
public static class MigrationExtensions {
public static ICreateTableWithColumnSyntax WithTimestamps(this ICreateTableWithColumnSyntax root) {
return root.
WithColumn("CreatedAt").AsDateTime().NotNullable().
WithColumn("UpdatedAt").AsDateTime().NotNullable();
}
}
Similarly, nearly every one of my tables has an int primary key called 'Id', so I think I'm going to add Table.CreateWithId("Foos") to always add that Id for me. Not sure ... I actually just started using FluentMigrator today, but you should always be refactoring when possible!
NOTE: If you do make helper/extension methods for your migrations, you should never ever ever change what those methods do. If you do, someone could try running your migrations and things could explode because the helper methods you used to create Migration #1 works differently now than they did earlier.
Here is the code for creating columns incase it helps you create helper methods: https://github.com/schambers/fluentmigrator/blob/master/src/FluentMigrator/Builders/Create/Column/CreateColumnExpressionBuilder.cs
How about extending like this:
public static class StringMaxMigratorExtensions
{
public static ICreateTableColumnOptionOrWithColumnSyntax AsStringMax(this ICreateTableColumnAsTypeSyntax createTableColumnAsTypeSyntax)
{
return createTableColumnAsTypeSyntax.AsCustom("nvarchar(max)");
}
public static IAlterColumnOptionSyntax AsStringMax(this IAlterColumnAsTypeSyntax alterColumnAsTypeSyntax)
{
return alterColumnAsTypeSyntax.AsCustom("nvarchar(max)");
}
}
While looking into forms authorizing/authentication, I found that it is possible to do role based authorizing by adding an array of roles to a FormsAuthenticationTicket. That way I can write
User.IsInRole(role from database)
But is there any way to do the same thing with permissions on a role like :
if (User.IsInRole(role from database)) {
if (User.CanRead()) {
//--- Let the user read
}
if (User.CanWrite()) {
//--- Let the user write
}
}
I have read a couple of articles and forum post's where permission is added to the array instead of the roles, resulting in using
User.IsInRole(permission from database)
However that's not the same thing. Hope someone can give some input on this matter, throw a link to an article or better yet, an code sample.
You're better off changing the way you think about a role. Use the term "permission" or "claim" if that helps. Then create all the roles you need and link a given user to all the necessary roles.
One user can belong to multiple roles. This way, the following simple code will work fine and you don't need to build your own unique way of how things work.
if(User.IsInRole(someRole) && User.IsInRole(someOtherRole))
{
// do something
}
You can make some C# extension methods to make this more readable too:
if(User.IsInSomeRoleAndOtherRole())
{
// do something
}
The extension methods can look something like the following. Create a new class with the following code, then include the class namespace in your code, and you can use the extension method as shown above.
using System.Security.Principal;
namespace MyCompany
{
public static class MyExtensions
{
public static bool IsInSomeRoleAndOtherRole(this IPrincipal principal)
{
if (!principal.IsInRole("someRole"))
return false;
if (!principal.IsInRole("someOtherRole"))
return false;
return true; // the user meets the requirements
}
}
}