My Angular client application is using MSAL in order to communicate with Azure B2C and retrieve the id token, refresh token and access token. These are in my localstorage after login.
I'm also using openapi generator to generate my services for my client application. The thing is, whenever I make a call to my backend, it is resulting as a 401.
The controller:
[Authorize]
[RequiredScope("example.read")]
[HttpGet(Name = "GetJobs")]
public async Task<ActionResult<IEnumerable<JobDTO>>> Index(int pageNumber, int pageSize, string? titleDesc, string? category)
{
var owner = CheckClaimMatch(ClaimTypes.NameIdentifier);
try
{
var result = await _jobModel.GetAllJobs(pageNumber, pageSize, titleDesc, category);
return Ok(result);
} catch (Exception ex)
{
return BadRequest(ex);
}
}
And here is my (simplified) openapi configuration:
openapi: 3.0.3
info:
title: EXAMPLE REST API
description: Api for the new example application
version: 1.0.0
servers:
- url: "https://{hostname}:{port}/{basePath}/"
variables:
hostname:
default: localhost
port:
default: "7051"
basePath:
default: api
tags:
- name: Job
paths:
/Jobs:
get:
operationId: getJobs
security:
- AzureOAuth:
- example.read
tags:
- Job
parameters:
- in: query
name: titleDesc
schema:
type: string
responses:
200:
description: Returns requested page
content:
application/json:
schema:
$ref: "#/components/schemas/JobPage"
components:
securitySchemes:
AzureOAuth:
type: oauth2
description: This API uses OAuth2 with authorizationCode grant flow.
flows:
authorizationCode:
authorizationUrl: https://example.b2clogin.com/example.onmicrosoft.com/B2C_1_SignUpAndSignIn/oauth2/v2.0/authorize
tokenUrl: https://example.b2clogin.com/example.onmicrosoft.com/B2C_1_SignUpAndSignIn/oauth2/v2.0/token
scopes:
example.read: read
example.write: write
schemas:
Job:
type: object
required:
- title
- category
- teleworkingDays
description: Job information
properties:
id:
type: integer
format: int64
title:
type: string
security:
- AzureOAuth:
- example.read
- example.write
I'm using oauth2 according to Azure's documentation.
Here is the post executed by the generated service.
Notice that the Bearer is empty.
I'm also wondering, if it's the correct way to do, because here I'm implementing it with the oauth2 way, but as I already have an access token in my localstorage, shouldn't just go with the bearer implementation ?
Also, testing with postman works completely fine, so I assume the controller part is fine.
Thank you
Related
I am a college student and during my intern my client gave me this project to convert his wordpress website into a mobile application while including existing features as well as some new features. The website is news website. I am also provided with wordpress admin panel credentials.
However, I am having hardtime fetching all data of website in json form. I tried using the wordpress api url: "https://example.com/wp-json/wp/v2/posts" as well as
"https://example.com/wp-json/wp/v2/posts?perpage=100" and
"https://example.com/wp-json/wp/v2/posts/?filter[limit]=100"
but none of them provided with whole data, it only rendered 10 latest news posts.
I am looking to get whole access to the website data myself. Is there any possible way for that? I want comments from the users on that news post, number of shares, likes, the related news section below post, everything.
Do I have to ask for the organization's main api or is there any other way? I am fluent in flutter and node js.
Flutter WordPress
Flutter WordPress is a library that allows for easy communication between a Flutter app and the WordPress backend. It uses WordPress REST API v2 for this interaction.
If your app is going to make use of authentication or other admin level APIs then the developer recommends you use these two authenthentication wordpress plugins:
Application Passwords
JWT Authentication for WP REST API (recommended)
How to use Flutter WordPress
1.Go to your pubspec.yaml then add the following as a dependency:
flutter_wordpress: ^0.1.4
You can check for the latest version here.
2.Import it in your code:
import 'package:flutter_wordpress/flutter_wordpress.dart' as wp;
3.You instantiate WordPress:
wp.WordPress wordPress;
// adminName and adminKey is needed only for admin level APIs
wordPress = wp.WordPress(
baseUrl: 'http://localhost',
authenticator: wp.WordPressAuthenticator.JWT,
adminName: '',
adminKey: '',
);
4.You then authenticate the user:
Future<wp.User> response = wordPress.authenticateUser(
username: 'ChiefEditor',
password: 'chiefeditor#123',
);
response.then((user) {
createPost(user);
}).catchError((err) {
print('Failed to fetch user: $err');
});
5.Here's how you can fetch wordpress posts and show them in your flutter app:
Future<List<wp.Post>> posts = wordPress.fetchPosts(
params: wp.ParamsPostList(
context: wp.WordPressContext.view,
pageNum: 1,
perPage: 20,
order: wp.Order.desc,
orderBy: wp.PostsOrderBy.date,
),
fetchAuthor: true,
fetchFeaturedMedia: true,
fetchComments: true,
);
6.And here's how you can fetch users:
Future<List<wp.User>> users = wordPress.fetchUsers(
params: wp.ParamsUserList(
context: wp.WordPressContext.view,
pageNum: 1,
perPage: 30,
order: wp.Order.asc,
orderBy: wp.UsersOrderBy.name,
role: wp.UserRole.subscriber,
),
);
7.And here's how to fetch comments:
Future<List<wp.Comment>> comments = wordPress.fetchComments(
params: wp.ParamsCommentList(
context: wp.WordPressContext.view,
pageNum: 1,
perPage: 30,
includePostIDs: [1],
),
);
8.Then creating a wordpress post via flutter is easy:
void createPost(wp.User user) {
final post = wordPress.createPost(
post: new wp.Post(
title: 'First post as a Chief Editor',
content: 'Blah! blah! blah!',
excerpt: 'Discussion about blah!',
author: user.id,
commentStatus: wp.PostCommentStatus.open,
pingStatus: wp.PostPingStatus.closed,
status: wp.PostPageStatus.publish,
format: wp.PostFormat.standard,
sticky: true,
),
);
post.then((p) {
print('Post created successfully with ID: ${p.id}');
postComment(user, p);
}).catchError((err) {
print('Failed to create post: $err');
});
}
Then to post a comment:
void postComment(wp.User user, wp.Post post) {
final comment = wordPress.createComment(
comment: new wp.Comment(
author: user.id,
post: post.id,
content: "First!",
parent: 0,
),
);
comment.then((c) {
print('Comment successfully posted with ID: ${c.id}');
}).catchError((err) {
print('Failed to comment: $err');
});
}
Download full example here.
I'm developing an app in Android Studio using amplify.
I need that unauthenticated users be able to read a type but need to signed in to create or modify it.
To achieve that I did the following:
I configured my auth to allow unauthenticated logins, following the steps in this documentation https://docs.amplify.aws/lib/auth/guest_access/q/platform/android
I configured my graphQL Api with Amazon cognito user pool as the default authorization type and IAM as additional authorization.
defined my type in schema.graphql this way
type Property #model\
#auth (
rules: [
{ allow: owner, operations: [create, update, delete, read]}
{ allow: private, operations: [create, read] }
{ allow: public, operations: [read], provider: iam }
]
)
#key(name: "propertiesByPrice" fields: ["modelType", "price"] queryField: "propertiesByPrice")
#key(name: "propertiesByLot" fields: ["modelType", "lot"] queryField: "propertiesByLot")
{
id: ID!,
imageUrl: String,
offerType: OfferType,
price: Int,
type: PropertyType,
rooms: Int,
bathrooms: Int,
parkingSpace: Int,
lot: Int,
state: String,
city: String,
neighborhood: String,
street: String,
number: String,
zipCode: String
modelType: String
}
So the guest users will be able to read the type Property but need to be signed in to create one and need to be the owner to modify it.
For tests I'm making the following query
Amplify.API.query(ModelQuery.list(Property::class.java),
{ result ->
Log.i(TAG, "listProperties: succeeded $result")
},
{ exception ->
Log.e(TAG, "listProperties: failed $exception")
})
I get the right response with signed in users but when I try to run it as guest i get the following error
W/CognitoUserSession: CognitoUserSession is not valid because idToken is null.
W/AWSMobileClient: signalTokensNotAvailable
Is there anything else I need to configure? Thanks in advance
I created a server stub using my own openapi-3.0.0 template from openapi-generator.
While implementing the API logic for creating resource, I'm referencing a component declared under requestBodies as follows
components:
requestBodies:
SamyojyaUser:
content:
application/json:
schema:
$ref: '#/components/schemas/SamyojyaUser'
application/xml:
schema:
$ref: '#/components/schemas/SamyojyaUser'
description: Samyojya User object that needs to be added to the system
required: true
The API is declared as follows
paths:
/samyojya-user:
post:
operationId: addSamyojyaUser
requestBody:
content:
application/json:
schema:
$ref: '#/components/requestBodies/SamyojyaUser'
x-content-type: application/json
However, while processing the request Ajv complains saying
can't resolve reference #/components/requestBodies/SamyojyaUser from id #
Looking like there seems to be some issue with registering requestBodies component. I see the other components showing up in the Ajv when I debug. I am tempted to use the user component directly at the path object but I want to customize the request body further. Any thoughts on tweaking it further?
References to #/components/requestBodies/... can only be used directly under requestBody and not under schema:
paths:
/samyojya-user:
post:
operationId: addSamyojyaUser
requestBody:
$ref: '#/components/requestBodies/SamyojyaUser'
Also, the indentation in the request body component in wrong - the description and required: true must be on the same level as content.
components:
requestBodies:
SamyojyaUser:
content:
application/json:
schema:
$ref: '#/components/schemas/SamyojyaUser'
application/xml:
schema:
$ref: '#/components/schemas/SamyojyaUser'
# vvvv Note the indentation level
description: Samyojya User object that needs to be added to the system
required: true
Use https://editor.swagger.io (or other validators) to validate your OpenAPI definitions before generating code.
So I'm creating a user endpoint with nodejs to add a user to the database , and for the api documentation I'm using swagger editor and I'm completely new to it.
what I want to do is add a user with login , password , avatar but that user has multiple roles I want to add to the database
what I have done in the yaml document in the swagger editor is this
/users/add:
post:
description: ''
operationId: AddUser
parameters:
- description: The user login
in: formData
name: user
required: true
type: string
- description: The user password
in: formData
name: password
required: true
type: string
- description: The user name
in: formData
name: username
required: true
type: string
- description: The user avatar
in: formData
name: avatar
required: true
type: file
- in: formData
name: roles
description: roles
required: false
type: array
items:
type: string
collectionFormat: multi
and it's kind of displaying what I want in the swagger editor
but what i'm getting in the UI is just an input field
In conclusion what I want to get is an inputted array which contains the user roles and input them in the database.
Thank you
What version of Swagger UI are you using? I am on version 2.1.1 and when I put the same definition as you I get the following input box for an array field.
Try upgrading to the newest version of Swagger UI.
Also, if you update the "in" field to be "query" the resulting URL will look like this:
http://localhost:8080/accounts?roles=admin%2Cguest%2Cuser
You can then access the array values in the URL parameters rather than in "formData".
My API seems to no longer parse properly using swagger-parser and swagger-tools latest versions after we did a full npm update on all our deps last night. However, I cannot track down what is causing these failures to happen since the API follows proper formatting for the 2.0 spec according to the docs.
Some information on the current setup:
swagger-parser: v3.3.0
swagger-tools: v0.9.7
node: v4.2.1
npm: v2.14.7
We are making use of swagger-tools connect middleware to create a stand-alone API app. Our setup for the api looks like this:
var app = require('connect')();
var cors = require('cors');
var swaggerTools = require('swagger-tools');
var swaggerParser = require('swagger-parser');
app.use(cors());
app.initialize = function (done) {
swaggerParser.parse('./api/swagger.yaml', function (err, api) {
if (err) throw err;
swaggerTools.initializeMiddleware(api, function (middleware) {
app.use(middleware.swaggerMetadata());
app.use(middleware.swaggerValidator());
var options = {
controllers: './controllers',
useStubs: process.env.NODE_ENV === 'development' ? true : false
};
app.use(middleware.swaggerRouter(options));
app.use(middleware.swaggerUi());
typeof done === 'function' && done();
});
});
return app;
};
Prior to the updates on the deps everything worked fine like this. However, now when being initialized our API is throwing a bunch of errors when swaggerTools.initializeMiddleware is being called.
A few chunks of our API are as follows:
./api/swagger.yaml
swagger: '2.0'
info:
version: 0.0.1
title: Insert API Title Here
schemes:
- http
basePath: /api/v1
consumes:
- application/json
produces:
- application/json
paths:
/users:
$ref: './api/paths/users.yaml'
/users/{userId}:
$ref: './api/paths/users-userId.yaml'
definitions:
User:
$ref: './api/models/user.yaml'
parameters:
userId:
in: path
name: userId
description: The user id of the user object.
required: true
type: integer
offset:
name: offset
in: query
description: The record to start the return set at.
required: false
type: integer
default: 0
minimum: 0
limit:
name: limit
in: query
description: The quota to limit the return set to.
required: false
type: integer
default: 10
orderBy:
name: orderBy
in: query
description: The field to order by.
required: false
type: string
sort:
name: sort
in: query
description: The sort order of the return set.
required: false
type: string
enum: [desc, asc]
default: asc
./api/paths/users.yaml
x-swagger-router-controller: Users
get:
tags:
- users
summary: Gets a list of all users.
description: ''
operationId: getUsers
parameters:
- $ref: '#/parameters/offset'
- $ref: '#/parameters/limit'
- $ref: '#/parameters/orderBy'
- $ref: '#/parameters/sort'
responses:
200:
description: OK
schema:
$ref: '#/definitions/UserCollection'
401:
description: Not Authorized
The errors we are seeing are things like this now:
#/paths/~1users/get/parameters/1/name: Parameter already defined: undefined
#/paths/~1users/get/parameters/2/name: Parameter already defined: undefined
#/paths/~1users/get/parameters/3/name: Parameter already defined: undefined
#/paths/~1users~1{userId}/get: API requires path parameter but it is not defined: userId
#/paths/~1users~1{userId}/put/parameters/1/name: Parameter already defined: undefined
#/paths/~1users~1{userId}/put: API requires path parameter but it is not defined: userId
#/paths/~1users~1{userId}/delete: API requires path parameter but it is not defined: userId
#/paths/~1users~1{userId}~1profile/get: API requires path parameter but it is not defined: userId
#/paths/~1users~1{userId}~1profile/post/parameters/1/name: Parameter already defined: undefined
#/paths/~1users~1{userId}~1profile/post: API requires path parameter but it is not defined: userId
I'm not sure where to go from here since I have tried everything to keep the API layout the same (broken into multiple files) vs. having to resort to putting it all into a single file. Our API is rather large and it is much easier to maintain broken into parts like this which used to work fine without issue.
Is there something I am missing, a step that needs to be done differently with the updates to swagger-parser and swagger-tools? Any help is appreciated.
It seems the jump between v2 to v3 of Swagger-Parser has changed the functionality of .parse() to no longer resolve references. Because of this it was causing portions of the API to not validate properly. Switching to .validate() instead of .parse() has fixed this issue. A handful of adjustments had to be made to the .yaml files to make it work with the new 2.0 standards but all is working again.