Urodził się 2 września 1949 r. w Krakowie.
Ukończył studia historyczne na Uniwersytecie Jagiellońskim. W czasie studiów był kilkakrotnie zatrzymywany za demonstracje antyreżimowe. W grudniu 1970 r. aresztowany.
Był związany z ruchem antykomunistycznej opozycji, m.in. Komitetem Obrony Robotników. Współpracował z podziemnymi wydawnictwami, a w 1979 r. kierował zespołem, który opublikował broszurę „Czego nie ma w podręcznikach”. Prowadził podziemne wykłady i kursy dla studentów, nauczycieli, uczniów licealnych i robotników.
W okresie działania legalnej „Solidarności” brał udział w pracy Wszechnicy Związkowej oraz w kursach organizowanych dla nauczycieli i studentów. Po wprowadzeniu stanu wojennego wszedł w skład redakcji dwumiesięcznika „Arka”. Nadal też prowadził działalność oświatową w podziemiu, m.in. wykłady dla Chrześcijańskiego Uniwersytetu Robotniczego (ChUR) w krakowskich Mistrzejowicach. Współpracował też z kilkoma legalnymi katolickimi tygodnikami.
Od 1977 r. pracował w Instytucie Historii Nauki i Oświaty PAN. W 1980 r. obronił pracę doktorską na Uniwersytecie Jagiellońskim. Wykładał najnowszą historię na Wydziale Filozoficznym oo. Jezuitów, przekształconym następnie w Akademię Ignatianum. Nadal prowadzi tam wykłady i seminaria. Przez jedną kadencję był prorektorem tej uczelni. W 1992 r. uzyskał habilitację, a w 2001 r. tytuł profesorski.
W 1990 r. był współzałożycielem i zastępcą redaktora naczelnego pierwszego niezależnego dziennika „Czas Krakowski”. Pracował m.in. jako redaktor naczelny rzeszowskiego dziennika „Nowiny”. W latach 1998-2002 i 2006-2007 był radnym Krakowa.
Od 2001 r. kierował Biurem Edukacji Publicznej Instytutu Pamięci Narodowej, a następnie był dyrektorem oddziału IPN w Krakowie.
Jest autorem wielu książek, m.in. „Miecz i tarcza komunizmu. Historia aparatu bezpieczeństwa w Polsce 1944-1990” (2007), „Polska w niewoli 1945-1989. Historia sowieckiej kolonii” (2015), „Solidarność 1980-1989: polska droga do Wolności” (2018).
Od 2007 r. jest posłem na Sejm RP.
W 2010 r. został członkiem Komitetu Politycznego PiS. W latach 2015-2019 pełnił funkcję wicemarszałka Sejmu VIII kadencji. 12 listopada 2019 r. wybrany na wicemarszałka Sejmu IX kadencji. Od 2015 r. jest przewodniczącym Klubu Parlamentarnego PiS.