How can i fix this error : { "detail": "Authentication credentials were not provided." } on Django RestFramework - api

I am getting
{"detail": "Authentication credentials were not provided." }
when I run Django Restframework code.
in my settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'NON_FIELD_ERRORS_KEY': 'error',
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
Here is where the culprit lies when i make a request to input values
class CashflowListAPIView(ListCreateAPIView):
serializer_class = CashflowSerializer
queryset = Cashflow.objects.all()
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self,serializer):
return serializer.save(owner=self.request.user)
def get_queryset(self):
return self.queryset.filter(owner = self.request.user)
class CashflowDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = CashflowSerializer
permission_classes = (permissions.IsAuthenticated,IsOwner,)
queryset = Cashflow.objects.all()
lookup_fields = 'id'
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
mind you, its supposed to work since user has gone through the authentication process VIA swagger API system on localhost:
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'Bearer': {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header'
}
}
}
How can i get my user to successfully input and fetch data without getting the message, { "detail": "Authentication credentials were not provided." }?
Your input is valued and appreciated. Thanks

Related

How to pass futures around to different endpoints in dask

I have a dask cluster (not asynchronous) setup in FastAPI, and I have created two endpoints. One submits the function to the dask cluster and the other gets polled by vuejs every so often and once the status is "finished" it stops polling. However dask has the issue that it forgets about futures if it thinks you do not need them. So I have a dictionary to hold onto them (similar to here. So I used that in my code and in my local container it worked. However deployed in pods on kubernetes I am able to print out the future key and future status to the logs, but the future is not there. The code for this is like as follows:
futures = {}
#router.post('/simulate')
async def simulate(request: Request, background_tasks: BackgroundTasks) -> object:
data = await request.json()
if data is None or not data:
raise HTTPException(status_code=422, detail={
"message": "Json body can't be empty"})
try:
data_is_cached = await get_cache(key=json.dumps(data, cls=CustomJSONEncoder))
if data_is_cached:
return {
"is_cached": True,
"result": data_is_cached
}
else:
# logic to create inputs_dict using data here
future = client.submit(run_simulation, inputs_dict)
futures[future.key] = [future, data]
return {
"is_cached": False,
"key": future.key
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
#router.get('/get_status/{key_id}')
async def check_status(key_id: str, request: Request, background_tasks: BackgroundTasks) -> object:
try:
future = futures[key_id][0]
data = futures[key_id][1]
if 'finished' in future.status:
result = future.result()
background_tasks.add_task(set_cache, key=json.dumps(data, cls=CustomJSONEncoder), data=result)
return {
"statusFinished": True,
"result": result
}
elif "pending" in future.status:
return {
"statusFinished": False,
"result": "pending"
}
else:
return {
"statusFinished": False,
"result": "error"
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
I then looked at dask datasets as a dataset can be shared across dask workers. But this always leave the state in "pending" I have to explicitly call future.result() why defies the purpose of what I am trying to do. This was in my container in localhost.
Here the code for this is:
#router.post('/simulate')
async def simulate(request: Request, background_tasks: BackgroundTasks) -> object:
data = await request.json()
if data is None or not data:
raise HTTPException(status_code=422, detail={
"message": "Json body can't be empty"})
try:
data_is_cached = await get_cache(key=json.dumps(data, cls=CustomJSONEncoder))
if data_is_cached:
return {
"is_cached": True,
"result": data_is_cached
}
else:
# logic to create inputs_dict using data here
future = client.submit(run_simulation, inputs_dict)
client.datasets[future.key] = future
client.datasets[f"{future.key}-data"] = data
return {
"is_cached": False,
"key": future.key
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
#router.get('/get_status/{key_id}')
async def check_status(key_id: str, request: Request, background_tasks: BackgroundTasks) -> object:
try:
future = client.get_dataset(key_id)
data = client.get_dataset(f"{key_id}-data")
if 'finished' in future.status:
result = future.result()
background_tasks.add_task(set_cache, key=json.dumps(data, cls=CustomJSONEncoder), data=result)
return {
"statusFinished": True,
"result": result
}
elif "pending" in future.status:
return {
"statusFinished": False,
"result": "pending"
}
else:
return {
"statusFinished": False,
"result": "error"
}
except Exception as e:
traceback.print_exc()
raise HTTPException(status_code=500, detail={
"message": str(e)})
I have the dask-worker to have 1 worker and 1 thread. Is there not a way to hold on to these futures properly?

Apache superset with Okta integration

https://github.com/apache/superset/issues/13948
I am configuring Okta with Apache Superset but it's redirecting me to the login page after authentication with message 'invalid login. Please try again.'
Below is my superset_config.py file:
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{
'name': 'okta', 'icon': 'fa-circle-o',
'token_key': 'access_token',
'remote_app': {
'client_id': '0oa8hoe9t1c8LfB1z357',
'client_secret': 'b8exxJID0BQOXlvMlQa5To5frU4EY7FX3cXDOMLM',
'api_base_url': 'https://dev-514411.okta.com/oauth2/v1/',
'client_kwargs': {
'scope': 'openid profile email groups'
},
'access_token_url': 'https://dev-514411.okta.com/oauth2/v1/token',
'authorize_url': 'https://dev-514411.okta.com/oauth2/v1/authorize'
}
}
]
Okta integration was supposed to work out of the box since Flask-AppBuilder 3.2.2, but it's not the case.
Here's what worked for me:
On your Okta's app settings, the field Sign-in redirect URIs should look something like this:
http://localhost:8088/oauth-authorized/okta
Your superset_config.py should contain something similar to this:
OKTA_BASE_URL = 'https://dev-<your-okta-id>.okta.com'
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{
'name': 'okta',
'token_key': 'access_token',
'icon': 'fa-circle-o',
'remote_app': {
'client_id': OKTA_CLIENT_ID,
'client_secret': OKTA_CLIENT_SECRET,
'client_kwargs': {
'scope': 'openid profile email groups'
},
'access_token_method': 'POST',
'api_base_url': f'{OKTA_BASE_URL}/oauth2/v1/',
'access_token_url': f'{OKTA_BASE_URL}/oauth2/v1/token',
'authorize_url': f'{OKTA_BASE_URL}/oauth2/v1/authorize',
'server_metadata_url': f'{OKTA_BASE_URL}/.well-known/openid-configuration',
},
}
]
from custom_sso_security_manager import CustomSsoSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
And finally, your custom_sso_security_manager.py, that must live on the same directory as your superset_config.py, should contain something like this:
from superset.security import SupersetSecurityManager
class CustomSsoSecurityManager(SupersetSecurityManager):
def oauth_user_info(self, provider, response=None):
if provider == 'okta':
user_info = self.appbuilder.sm.oauth_remotes[provider].parse_id_token(
response)
return {
'name': user_info['name'],
'email': user_info['email'],
'id': user_info['email'],
'username': user_info['email']
}
The important attributes on the object oauth_user_info returns are email and username, which will be used to match against your database's ab_user table records. If there isn't a matching record then the login will fail.

Vue js Django Rest Framework With JWT user authentication (getting anonymous user ) simplejwt simplejwt

I got the token.But it is not possible to get data this user. which URL to get data .
token work. //simplejwt simplejwt
class CustomerRetrieveView(generics.RetrieveAPIView):
queryset = Customer.objects.all()
permission_classes=(IsAuthenticated,)
def get(self,request):
???here correct?????
queryset=Customer.objects.get(id=request.user)
serializer=CustomerSerializer(queryset)
return Response(serializer.data)
url
??here correct?????
path('customers/????<int:id>???', views.CustomerRetrieveView.as_view()),
frontend
created() {
getAPI.get('???????????/customers????????', { headers: { Authorization: `Bearer ${this.$store.state.accessToken}` } })
.then(response => {
this.$store.state.APIData = response.data
})
.catch(err => {
console.log(err)
console.log(`Bearer ${this.$store.state.accessToken}`)
})
},
models
class Customer(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=11)
likecus=models.ManyToManyField(smartphone ,verbose_name="b")
def __str__(self):
return "User: {}, phone: {}".format(self.user, self.phone)
Serializer
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = '__all__'
I got the token.But it is not possible to get data this user. which URL to get data .
token workI got the token.But it is not possible to get data this user. which URL to get data .
token workI got the token.But it is not possible to get data this user. which URL to get data .
token work
you can do this
pip install djangorestframework-jwt
settings.py
from django.conf import settings
import datetime
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_ENCODE_HANDLER':
'rest_framework_jwt.utils.jwt_encode_handler',
'JWT_DECODE_HANDLER':
'rest_framework_jwt.utils.jwt_decode_handler',
'JWT_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_payload_handler',
'JWT_PAYLOAD_GET_USER_ID_HANDLER':
'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
'JWT_RESPONSE_PAYLOAD_HANDLER':
'rest_framework_jwt.utils.jwt_response_payload_handler',
'JWT_SECRET_KEY': settings.SECRET_KEY,
'JWT_GET_USER_SECRET_KEY': None,
'JWT_PUBLIC_KEY': None,
'JWT_PRIVATE_KEY': None,
'JWT_ALGORITHM': 'HS256',
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_LEEWAY': 0,
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
'JWT_AUDIENCE': None,
'JWT_ISSUER': None,
'JWT_ALLOW_REFRESH': False,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_AUTH_HEADER_PREFIX': 'JWT',
'JWT_AUTH_COOKIE': None,
}
urls.py
from rest_framework_jwt.views import obtain_jwt_token, refresh_jwt_token, verify_jwt_token
urlpatterns = [
path(r'^api-token-refresh/', refresh_jwt_token),
path(r'^api-token-auth/', obtain_jwt_token),
path(r'^api-token-verify/', verify_jwt_token),
]
curl -X POST -d "username=admin&password=password123" http://localhost:8000/api-token-auth/

How to add captcha required only for a particular condition yii2

I am trying make the captcha field required only when the number of failed login attempts exceed 3 times. For which I have written below code till now.
In LoginForm model I have added the below rules
public function rules()
{
return [
[['username', 'password'], 'required'],
['password', 'validatePassword'],
['verifyCode', 'captcha', 'when' => function($model) {
return $this->checkattempts();
}],
];
}
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addLoginAttempt($user->id);
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
public function checkattempts()
{
$user = $this->getUser();
$ip = $this->get_client_ip();
$data = (new Query())->select('*')
->from('login_attempts')
->where(['ip' => $ip])->andWhere(['user_ref_id' => $user->id])
->one();
if($data["attempts"] >=3){
return false;
}else{
return true;
}
}
public function addLoginAttempt($uid) {
$ip = $this->get_client_ip();
$data = (new Query())->select('*')
->from('login_attempts')
->where(['ip' => $ip])->andWhere(['user_ref_id' => $uid])
->one();
if($data)
{
$attempts = $data["attempts"]+1;
#Yii::$app->db->createCommand("UPDATE login_attempts SET attempts=".$attempts." where ip = '$ip' AND user_ref_id=$uid")->execute();
}
else {
Yii::$app->db->createCommand("INSERT into login_attempts (attempts, user_ref_id, ip) VALUES(1,'$uid', '$ip')")->execute();
}
}
Here I am validating the password first. If the password is incorrect then I am incrementing the count by 1. This part is working fine. The count is incrementing successfully.
After this I am trying to get the count of failed attempts while validating captcha using the function checkattempts(), but it is not working.
Can anyone please tell me where I have made mistake.
Thanks in advance.
In your model:
if (!$model->checkattempts())
//show the captcha
Then, in your model rules you'll need something like:
['captcha', 'captcha'],
In your case, what you can do is use different scenarios depending on the user attempts, and in one scenario (more than X attempts) make the captcha required.
More documentation about the captcha and about scenarios.

Laravel API give json response when got error This action is unauthorized

I newbie in Laravel API. There is an update function which only allows users to update their own post. It worked. When users try to update other user's post, it alswo worked, but it shows the error like this image. Actually i want it show in response json.
I want to show message like this
{
"status": "error",
"message": "This action is unauthorized",
}
This is my code for PostController.
public function update(Request $request, Post $post)
{
$this->authorize('update', $post);
//this will check the authorization of user but how to make if else statement, if the post belong to the user it will show this json below but if the post belong to other, it will show error message(response json)
$post->content = $request->get('content', $post->content);
$post->save();
return fractal()
->item($post)
->transformWith(new PostTransformer)
->toArray();
}
This code for PostPolicy
public function update(User $user, Post $post)
{
return $user->ownsPost($post);
}
This is code for User model
public function ownsPost(Post $post)
{
return Auth::user()->id === $post->user->id;
}
This code for AuthServiceProvider
protected $policies = [
'App\Post' => 'App\Policies\PostPolicy',
];
Hope anyone can help me.
I'm using Laravel 5.4
In the app/Exceptions/Handler.php class you can change the render function like so
public function render($request, Exception $exception)
{
$preparedException = $this->prepareException($exception);
if ($preparedException instanceof HttpException) {
return response(
[
'message' => sprintf(
'%d %s',
$preparedException->getStatusCode(),
Response::$statusTexts[$preparedException->getStatusCode()]
),
'status' => $preparedException->getStatusCode()
],
$preparedException->getStatusCode(),
$preparedException->getHeaders()
);
}
return parent::render($request, $exception);
}
Or if you look further in the rendering, overriding the renderHttpException might be a little safer. This will remove the custom error pages in views/errors
protected function renderHttpException(HttpException $e)
{
return response(
[
'message' => sprintf(
'%d %s',
$e->getStatusCode(),
Response::$statusTexts[$e->getStatusCode()]
),
'status' => $e->getStatusCode()
],
$e->getStatusCode(),
$e->getHeaders()
);
}