Django rest framework token authentication AngularJS - angularjs

I am fairly new to Django and Token authentication as well as AngularJS. So far I have made Django backend and AngularJS frontend. I installed the Django Rest Framework and got the standard token authentication working as far as doing:
$scope.login = function () {
$http.post('link to my api', {
'username': $scope.data.username,
'password': $scope.data.password,
}).success(function () {
$state.go('tab');
})
.error(function () {
});
};
So far I succeed by getting a token with the right username and password. I see so much options about authentication that I don't know what fits for me anymore and where to start as I don't get a lot of information on the standard Token authentication. I have an Ionic app with a login screen, the Django backend has the users stored. I want to be able to login with a user account that resides within the Django database. Whenever that is done the user got permission to use the app. Later on it should be possible for example to get the credentials like personal details of the logged in user. Let's say I use the TokenAuthentication like above, I get the token. But how can I get the user credentials or whatever else from Django later on by that token? I am totally lost. If someone could please bring me into the right approach and material.

I found out that when you implement the following DRF permissions:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
and you make viewsets like on http://www.django-rest-framework.org/#example that it automatically requires a token to view those viewsets. So then you could work with that token to send requests to the api to get specific data.

Related

ASP.NET 6 WebAPI Authentication with SSO

I have an ASP.NET 6.0 Web API project. I would like to add authentication and authorization to it, but it must use SSO via Azure.
We already have a SPA application that does this, it uses the Angular MSAL library to redirect the user to an SSO Login page, then returns to the SPA with an access token. The access token is then added to the header of each request to the Web API, which uses it to enforce authentication.
Now we want to share our web API with other teams within our organization, and we would like to have that login process just be another API call, rather than a web page.
Conceptually, a client would hit the /login endpoint of our API, passing in a userID and password. The web API would then get an access token from Azure, then return it as the payload of the login request. It's then up to the client to add that token to subsequent request headers.
I have done this with regular ASP.NET Identity, where all of the user and role data is stored in a SQL database, but since our organization uses SSO via Azure Active Directory, we would rather use that.
I have researched this topic online, and so far all of the examples I have seen use a separate SPA, just like we already have. But as this is a web api, not a front-end, we need to have an API method that does this instead.
Is this even possible? I know Microsoft would rather not have user credentials flow through our own web server, where a dishonest programmer might store them for later misuse. I understand that. But I'm not sure there's a way around this.
Thanks.
I believe you are looking for the Resource Owner Password (ROP) flow. You can use IdentityModel.OidcClient to implement it.
Sample code:
public class Program
{
static async Task Main()
{
// call this in your /login endpoint and return the access token to the client
var response = await RequestTokenAsync("bob", "bob");
if (!response.IsError)
{
var accessToken = response.AccessToken;
Console.WriteLine(accessToken);
}
}
static async Task<TokenResponse> RequestTokenAsync(string userName, string password)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(Constants.Authority);
if (disco.IsError) throw new Exception(disco.Error);
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "roclient",
ClientSecret = "secret",
UserName = userName,
Password = password,
Scope = "resource1.scope1 resource2.scope1",
Parameters =
{
{ "acr_values", "tenant:custom_account_store1 foo bar quux" }
}
});
if (response.IsError) throw new Exception(response.Error);
return response;
}
}
Sample taken from IdentityServer4 repository where you can find more ROP flow client examples.
I would recommend that you don't go with this implementation and instead have all clients obtain their access tokens directly from Azure AD like you did with your Angular SPA.

How to validate AzureAD accessToken in the backend API

I just wanted to know how can we validate the azure ad access token in a backend API in my case i.e. Django rest framework.
Consider that I have a single page app or a native app and a backend API (django rest framework) completely independen of each other. In my case if my single page app/native app wants to access certain data from the backend API, and inorder to access the API, user should be logged in the backend API.
So what my approch is to make use of MSAL library to get the access token from the SPA/native app and then once token is acquired, pass that token to backend API, validate it, get the user info from graph api. If user exists in the DB then login the user and pass the required info. If user info doesn't exist then create the user, login and pass the info from the API.
So my question is when I pass the access token to my backend api, how can I validate that the token that a user/SPA/native app has passed to backend API is valid token or not?
Is it just we need to make an API call to graph API endpoint with accessToken that user/SPA/native passed and if it is able to get the user data with the accessToken then then token is valid or if it fails then the accessToken is invalid.
Is it the general way to validate the token or some better approach is there? Please help
Good day sir, I wanna share some of my ideas here and I know it's not a solution but it's too long for a comment.
I created a SPA before which used msal.js to make users sign in and generate access token to call graph api, you must know here that when you generate the access token you need to set the scope of the target api, for example, you wanna call 'graph.microsoft.com/v1.0/me', you need a token with the scope 'User.Read, User.ReadWrite' and you also need to add delegated api permission to the azure app.
So as the custom api of your own backend program. I created a springboot api which will return 'hello world' if I call 'localhost:8080/hello', if I wanna my api protected by azure ad, I need to add a filter to validate all the request if has a valid access token. So I need to find a jwt library to decode the token in request head and check if it has a token, if the token has expired and whether the token has the correct scope. So here, which scope is the correct scope? It's decided by the api you exposed in azure ad. You can set the scope named like 'AA_Custom_Impression', and then you can add this delegate api permission to the client azure ad app, then you that app to generate an access token with the scope of 'AA_Custom_Impression'. After appending the Bearer token in calling request, it will be filtered by backend code.
I don't know about python, so I can just recommend you this sample, you may try it, it's provided by microsoft.
I've solved the similar issue. I don't found how to directly validate access token, but you can just call graph API on backend with token you've got on client side with MSAL.
Node.js example:
class Microsoft {
get baseUrl() {
return 'https://graph.microsoft.com/v1.0'
}
async getUserProfile(accessToken) {
const response = await got(`${this.baseUrl}/me`, {
headers: {
'x-li-format': 'json',
Authorization: `Bearer ${accessToken}`,
},
json: true,
})
return response.body
}
// `acessToken` - passed from client
async authorize(accessToken) {
try {
const userProfile = await this.getUserProfile(accessToken)
const email = userProfile.userPrincipalName
// Note: not every MS account has email, so additional validation may be required
const user = await db.users.findOne({ email })
if (user) {
// login logic
} else {
// create user logic
}
} catch (error) {
// If request to graph API fails we know that token wrong or not enough permissions. `error` object may be additionally parsed to get relevant error message. See https://learn.microsoft.com/en-us/graph/errors
throw new Error('401 (Unauthorized)')
}
}
}
Yes we can validate the Azure AD Bearer token.
You can fellow up below link,
https://github.com/odwyersoftware/azure-ad-verify-token
https://pypi.org/project/azure-ad-verify-token/
We can use this for both Django and flask.
You can directly install using pip
but I'm not sure in Django. If Django install working failed then try to copy paste the code from GitHub
Validation steps this library makes:
1. Accepts an Azure AD B2C JWT.
Bearer token
2. Extracts `kid` from unverified headers.
kid from **Bearer token**
3. Finds `kid` within Azure JWKS.
KID from list of kid from this link `https://login.microsoftonline.com/{tenantid}/discovery/v2.0/keys`
4. Obtains RSA key from JWK.
5. Calls `jwt.decode` with necessary parameters, which inturn validates:
- Signature
- Expiration
- Audience
- Issuer
- Key
- Algorithm

Looking for more info with the loopback + passport strategy

I'm interested in creating an application using loopback and passport (and AngularJS).
I see this example app which I have up and running and I'm able to log in via google. What I don't quite get is how this should work with an AngularJS app. Using the example app, everything is done on the server (auth). Once I'm logged in, how does this relate to the Access Token needed between the client (AngularJS) and the loopback server? I can see the user created with the access token from google and other identity information but how does that "connect" with the access token required by the client (AngularJS)?
I'm mostly beginning with it as well but here is what I grasped so far:
3rd party provider <--- OAuth token ---> Loopback app <--- LB Token ---> Client
The OAuth token, used to interact with third party providers is abstracted by passport and so far I never needed to interact with it.
Basically, once you are logged in using OAuth, a LB token must be generated and provided to the user so that the user can be further identified.
To do that, I implemented some custom code inside serializeUser. My custom user model is called Client
app.serializeUser = function(userDataToSerialize, done) {
app.models.Client.create({
email: userDataToSerialize.email,
password: userDataToSerialize.password
},
function(err, user) {
if (err) return done(err);
app.models.Client.generateVerificationToken(user, function(err, token) {
if(err) return done(err);
done(null, {
userId: user.id,
accessToken: token
});
});
};
I create a new client, then generate a token for that user. Calling done(null,..) with both the token and user id will let passport put this data into the session, and thus should be accessible client-side.
This way, the Angular app should be able to get the user id and access token, be properly identified by Loopback, then the Loopback app can make requests to third-party providers on behalf of identified user.
Hope this helps

token authentication on Django REST framework + Angular project

I'm using DRF and Angular, which client environment is a mobile devices.
I've found out a django-rest-auth package.
I haven't hesitate to choice for that, because that provides a TokenAuthentication feature, which is suitable with a mobile client.
When I sent a login request, client receives a token.
Then, I was add a the bellow in request success callback.
login: function(username, password) {
return $http.post('http://192.168.0.3:8000/rest-auth/login/', {
'username':username,
'password':password,
}).success(function(data) {
$http.defaults.headers.common.Authorization = 'Token ' + data.key;
Account.authenticated = true;
console.log("login success", data)
})
At server's console, output about incoming request is the bellow
'HTTP_AUTHORIZATION': 'Token 3fae470d169adb550e538c99a754fcfbe3485f75'
But, I saw an unexpected result, like this:
request.user AnonymousUser
request.auth None
According to here, If I send a request with token, which extra authentication works will be processed by itself.
Should I add an other code for complete authentication?
(ex. register a token into django's session storage.)
I would like to hear your advice.
I solved for a problem, which cause is just stupid mistakes
I didn't look carefully at the reference documents.
To use the TokenAuthentication scheme you'll need to configure the authentication classes to include TokenAuthentication, and additionally include rest_framework.authtoken in your INSTALLED_APPS setting:
So I had added the configuration in settings.py.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
# I add this config
'rest_framework.authentication.TokenAuthentication',
)
}
After send a login request terminal to server, then If I request with the "GET", terminal console outputs like the below.
request.user admin
request.auth 626ba4b1357cb472fc4bb0c58afb026cf21dd175

How to pass basic auth header to REST endpoint after Forms Authentication sign in?

I have a Backbone/RequireJS application built on top of .NET MVC4. I am using Forms Authentication to authenticate the user against our back end data store, and this is working great.
Our services layer is a .NET Web Api Project (RESTful API), and is using a tokenized approach to auth (initial request includes basic auth header. If auth is successful, response payload includes authentication token. Subsequent requests pass the token).
What I'm not sure about is how to now authenticate against our services layer. I'm sure I'll have to pass the auth header, but not sure how to generate the token, as I won't have username/password in my JS.
Should I bypass Forms auth altogether here, and simply make an ajax request over SSL? I can POST to the /Account/Login action just as well, and use the Membership Provider to validate credentials. If successful, I can add the Auth header for initial request & use auth token for subsequent requests.
Example of adding auth header / custom token here:
$.ajaxSetup({
'beforeSend': function (xhr) {
if($.cookie("AuthToken")) {
xhr.setRequestHeader("CustomTokenHeader", $.cookie("AuthToken"));
} else {
var token = methodToBase64EncodeUsernamePassword(username, password);
xhr.setRequestHeader("Authentication", "Basic " + token);
}
}
});
Take a look at this solution, which is based off a screencast I cannot seem to find again. If I can find it, I will update the answer. You should be able to follow the solutions easily though. The one you are looking for is PerRouteMHOwnershipSample. I believe the best practice is to 'bypass Forms auth altogether here, and simply make an ajax request over SSL'. Any api route you want to secure, will be filtered and a token will then need to be passed from your app and decoded on the server. I would personally not look at using Forms Authentication to secure your api.

Resources