I would like to delete all my invalidated json web tokens from the database that have expired already. I'm using TypeORM and I think I have to use the query builder for that.
My token entity has a column representing the time the token expires
#Column()
public expiresOn: Date;
I want to setup a cronjob deleting all expired tokens from the database. So what I currently have is
#Interval(2000) // gets called every 2 seconds - for demo purposes
public async handleInterval(): Promise<void> {
const currentDate: Date = new Date();
const deleteExpiredTokensQuery: SelectQueryBuilder<Token> = this.tokensRepository.createQueryBuilder('token');
deleteExpiredTokensQuery.where('token.expiresOn <= :currentDate', { currentDate });
await deleteExpiredTokensQuery.delete();
}
Unfortunately no token gets deleted, although the token expires on
1970-01-19 07:32:20.093
So how to fix my query? I think the plain Query would be
DELETE FROM tokens WHERE expiresOn < GETDATE()
Update
I thought I would have to create a delete query builder
const deleteExpiredTokensQuery: DeleteQueryBuilder<Token> = this.tokensRepository.createQueryBuilder('token');
but then I get this error
Type 'SelectQueryBuilder' is missing the following properties
from type 'DeleteQueryBuilder': output, returning,
createDeleteExpression
By calling delete() on QueryBuilder it only declares this query as a deletion. To execute the query you have to call execute(). See the docs for delete.
await this.tokensRepository
.createQueryBuilder('token')
.delete()
.where('token.expiresOn <= :currentDate', { currentDate })
.execute();
About the second problem: You do not have to specify the type of the variable explicitly, since it get inferred automatically.
Related
My problem is I want to change the document/table unique ID from string to int in firebase realtime database.
This is how it looks in my database:
.
I want to look like this:
.
This is my code in inserting data to firebase:
public async Task<bool> Save(CUSTOMER customer)
{
//var token = await authProvider.CreateUserWithEmailAndPasswordAsync(customer.CusEmail,customer.CusPassword);&& !string.IsNullOrEmpty(token.FirebaseToken);
var token = await authProvider.CreateUserWithEmailAndPasswordAsync(customer.CusEmail, customer.CusPassword);
var data = await firebaseClient.Child(nameof(CUSTOMER)).PostAsync(JsonConvert.SerializeObject(customer));
if (!string.IsNullOrEmpty(data.Key) && !string.IsNullOrEmpty(token.FirebaseToken))
{
return true;
}
return false;
}
When you call PostAsync, Firebase creates a new child node with its own unique ID for that data. The IDs always have the form that you see in your first screenshot, and there's no way to change that.
To specify your own ID, generate that ID in your client-side application code, pass it to the API as an additional Child() call, and use Put instead of Post. For example:
firebaseClient.Child(nameof(CUSTOMER)).Child("4815").PutAsync(JsonConvert.SerializeObject(customer));
If the number you want to use is based on the existing keys in the database, you'll need to use a transaction to perform the necessary read-then-write sequence.
Since you're considering using numeric keys, I recommend checking out Best Practices: Arrays in Firebase.
I did this UserFactory:
export class UserFactory {
create(values = {}): User {
return User.create({
// defaults
name: 'Jerry',
age: 99,
// overrides
...values,
})
}
}
It is my understanding that Entity.create does not persist the entity in my db, it only creates the instance (I'm using the BaseEntity/ORM pattern). This is precisely what I want. However, it still requires a connection to work. In my tests I need to do something like:
const connection = await db()
const user = new UserFactory().create()
await connection.destroy()
Otherwise, I get DataSource is not set for this entity. I can't understand why a connection is needed when it's not even saving it.
I guess I could use new User() but unfortunately there is no set methods to bulk apply my values then.
How can I set my values and get an entity instance without unnecessary db connections here?
I'm facing an issue with TFS.
I'm trying to fetch commits by date range( Id range does not work for me as as it returns alphabetically sorted revisions, not based on when creation time. So I never got revision in specified range).
GitCommitRef.Committer.Date returns in UTF format
but GitQueryCommitsCriteria.FromDate expects date in format the user set in his UserProfile->Locale->TimeZone.
Looking for .Net api to extract this value. I'm aware of below REST api(though couldn't find its equivalent .net api) , but it doesn't provide me other user's timezone value.
http://tfsemea1.ta.philips.com:8080/tfs/TPC_Region13//_api/_common/GetUserProfile?__v=5
How to get timezone value for any user?
Alternatively how can i make ID range work?
Based on my test I cannot find the Time Zone property for a valid user with the .net API.
You can use below sample code to get the user list (unfortunately cannot find the Time Zone for users):
Note: You need to install the Microsoft.TeamFoundationServer.ExtendedClient Nuget package.
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
TfsConfigurationServer tcs = new TfsConfigurationServer(new Uri("http://server:8080/tfs"));
IIdentityManagementService ims = tcs.GetService<IIdentityManagementService>();
TeamFoundationIdentity tfi = ims.ReadIdentity(IdentitySearchFactor.AccountName, "[TEAM FOUNDATION]\\Team Foundation Valid Users", MembershipQuery.Expanded, ReadIdentityOptions.None);
TeamFoundationIdentity[] ids = ims.ReadIdentities(tfi.Members, MembershipQuery.None, ReadIdentityOptions.None);
foreach (TeamFoundationIdentity id in ids)
{
if (id.Descriptor.IdentityType == "System.Security.Principal.WindowsIdentity")
{ Console.WriteLine(id.DisplayName); }
{ Console.WriteLine(id.UniqueName); }
}
Console.ReadLine();
}
}
}
And there isn't such a REST API to get all users and their profiles for now.
We can only get the current login user profile with the REST API, So as a workaround you can ask all the users to check and back their Time Zone to you.
No idea for the ID range.
In our website we used to use access_token when logging people with Google Sign In. First, we redirect the user to google, user brings the access_token to us, and we validate that token to make sure the user is the actual Google user.
Then, we needed a Google sign-in feature for our Android app, so I wanted the Android developer to bring access_token to us. He replied he couldn't. I searched about that finding almost no documentation about access_token. In documentation, Google says me to use the "id_token".
OK, I wanted the developer to bring me the id_token, and I have successfully verified the token's integrity. Then I wanted to implement the same for websites.
My c# code is:
string googleId = GoogleJsonWebSignature.ValidateAsync(idToken).Result.Subject;
It worked when I ran it locally, but when I tried in production, it gave an error: JWT is not yet valid
Is id_token the correct way to send to the backend and verify? I found another option too: code.
Code is something like A/12112312......
Access_token is something like ya29.somemorestring
My question is, Which one is correct to send to the backend? By the way, I think access_token is sort of deprecated or something like that.
Yes, you should be using the id_token. You get the id_token on the client side using this:
var id_token = googleUser.getAuthResponse().id_token;
and validating it on the server side using (do in a try/catch block to catch any errors):
token = await GoogleJsonWebSignature.ValidateAsync(idToken);
The JWT is not yet valid error is due to the time on your server being slow. Even a few seconds slow will cause this problem. To be sure of this working all the time, you'll need to implement a custom clock which gets an accurate time from somewhere. Here's an example using NNTP:
public class AccurateClock : Google.Apis.Util.IClock
{
const int UpdateIntervalMinutes = 60;
const string NntpServer = "time.nist.gov";
private TimeSpan _timeOffset;
private DateTime _lastChecked;
public AccurateClock()
{
_timeOffset = TimeSpan.FromSeconds(0);
_lastChecked = DateTime.MinValue;
}
private DateTime GetTime()
{
try
{
if (DateTime.Now.Subtract(_lastChecked).TotalMinutes >= UpdateIntervalMinutes)
{
// Update offset
var client = new TcpClient(NntpServer, 13);
DateTime serverTime;
using (var streamReader = new StreamReader(client.GetStream()))
{
var response = streamReader.ReadToEnd();
var utcDateTimeString = response.Substring(7, 17);
serverTime = DateTime.ParseExact(utcDateTimeString, "yy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
_timeOffset = DateTime.UtcNow.Subtract(serverTime);
_lastChecked = DateTime.Now;
}
var accurateTime = DateTime.UtcNow.Subtract(_timeOffset);
return accurateTime;
}
catch (Exception ex)
{
return DateTime.UtcNow;
}
}
public DateTime Now
{
get
{
return GetTime().ToLocalTime();
}
}
public DateTime UtcNow
{
get
{
return GetTime();
}
}
}
You then pass the custom clock to the validation method.
token = await GoogleJsonWebSignature.ValidateAsync(idToken, new AccurateClock());
Please note: This will update the difference between the correct time and the local machine time every time the class is created, so you really want to register this as a Singleton in whatever IOC container you are using and pass the reference to the validator instead. It will then recheck the time using NNTP every hour. If you are not using an IOC Container you could make the class static.
id_token is a JWT token, that you validate and extract information such as "email", "name" etc. This is actually what you need in a regular case.
code and access_token are part of the flow when a user doesn't use your app in current moment but your app wants to make any actions behalf of them. Google calls it offline access https://developers.google.com/identity/sign-in/web/server-side-flow
I need to send the user a url with a token so that the user can click on that link and view my page without logging in to the system. This user has been created in my system, but has not set a password, I want this user not to see the other pages but only see the page that I allow.
Please help me to come up with a solution in this regard.
Thanks all.
Create one table in your database like below
Insert the entry in this table when you send the link to particular user. As an example, Here I inserted two entries for UserId 10 and 12
Make one procedure or function to validate the token against request.
CREATE PROCEDURE sp_ValidateUserIdAndTokenId
#UserId INT,
#TokenId varchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF ISNULL(#UserId,0) <> 0 AND ISNULL(#TokenId,'') <> ''
BEGIN
IF EXISTS(SELECT 1 FROM UserToken WHERE UserID = #UserId AND TokenID = #TokenId)
BEGIN
Declare #TokenInsertedDateTime AS DateTime
Declare #IsTokenExpired AS Bit
SET #TokenInsertedDateTime = (SELECT TokenInserted FROM UserToken WHERE UserID = #UserId AND TokenID = #TokenId)
-- Here Calculate the token time difference in minutes for one day i.e. 1440 minutes.
SET #IsTokenExpired = (SELECT CASE WHEN DATEDIFF(MINUTE, #TokenInsertedDateTime, GETDATE()+1) > 1440 THEN 0 ELSE 1 END)
SELECT #IsTokenExpired
END
END
END
Now, When request comes in controller's action at that time you have to make a call the database to identify the Token and User in newly created table and determine the request is valid or not(You can also calculate the interval of time for particular token).
[HttpGet]
[AllowAnonymous]
public ActionResult Add(int userId, string tokenId)
{
// Determine the request with tokenId and validate your tokenId
// make the database call of created procedure or function and validate your userid and token here.
return View();
}